1
/* $Id: os_timestamp_common.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include <pj/compat/high_precision.h>
23
#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
25
#define U32MAX (0xFFFFFFFFUL)
26
#define NANOSEC (1000000000UL)
27
#define USEC (1000000UL)
30
#define u64tohighprec(u64) ((pj_highprec_t)((pj_int64_t)(u64)))
32
static pj_highprec_t get_elapsed( const pj_timestamp *start,
33
const pj_timestamp *stop )
35
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
36
return u64tohighprec(stop->u64 - start->u64);
38
pj_highprec_t elapsed_hi, elapsed_lo;
40
elapsed_hi = stop->u32.hi - start->u32.hi;
41
elapsed_lo = stop->u32.lo - start->u32.lo;
43
/* elapsed_hi = elapsed_hi * U32MAX */
44
pj_highprec_mul(elapsed_hi, U32MAX);
46
return elapsed_hi + elapsed_lo;
50
static pj_highprec_t elapsed_msec( const pj_timestamp *start,
51
const pj_timestamp *stop )
54
pj_highprec_t freq, elapsed;
56
if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
59
/* Convert frequency timestamp */
60
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
61
freq = u64tohighprec(ts_freq.u64);
63
freq = ts_freq.u32.hi;
64
pj_highprec_mul(freq, U32MAX);
65
freq += ts_freq.u32.lo;
68
/* Avoid division by zero. */
69
if (freq == 0) freq = 1;
71
/* Get elapsed time in cycles. */
72
elapsed = get_elapsed(start, stop);
74
/* usec = elapsed * MSEC / freq */
75
pj_highprec_mul(elapsed, MSEC);
76
pj_highprec_div(elapsed, freq);
81
static pj_highprec_t elapsed_usec( const pj_timestamp *start,
82
const pj_timestamp *stop )
85
pj_highprec_t freq, elapsed;
87
if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
90
/* Convert frequency timestamp */
91
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
92
freq = u64tohighprec(ts_freq.u64);
94
freq = ts_freq.u32.hi;
95
pj_highprec_mul(freq, U32MAX);
96
freq += ts_freq.u32.lo;
99
/* Avoid division by zero. */
100
if (freq == 0) freq = 1;
102
/* Get elapsed time in cycles. */
103
elapsed = get_elapsed(start, stop);
105
/* usec = elapsed * USEC / freq */
106
pj_highprec_mul(elapsed, USEC);
107
pj_highprec_div(elapsed, freq);
112
PJ_DEF(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
113
const pj_timestamp *stop )
115
pj_timestamp ts_freq;
116
pj_highprec_t freq, elapsed;
118
if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
121
/* Convert frequency timestamp */
122
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
123
freq = u64tohighprec(ts_freq.u64);
125
freq = ts_freq.u32.hi;
126
pj_highprec_mul(freq, U32MAX);
127
freq += ts_freq.u32.lo;
130
/* Avoid division by zero. */
131
if (freq == 0) freq = 1;
133
/* Get elapsed time in cycles. */
134
elapsed = get_elapsed(start, stop);
136
/* usec = elapsed * USEC / freq */
137
pj_highprec_mul(elapsed, NANOSEC);
138
pj_highprec_div(elapsed, freq);
140
return (pj_uint32_t)elapsed;
143
PJ_DEF(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
144
const pj_timestamp *stop )
146
return (pj_uint32_t)elapsed_usec(start, stop);
149
PJ_DEF(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
150
const pj_timestamp *stop )
152
return (pj_uint32_t)elapsed_msec(start, stop);
155
PJ_DEF(pj_uint64_t) pj_elapsed_msec64(const pj_timestamp *start,
156
const pj_timestamp *stop )
158
return (pj_uint64_t)elapsed_msec(start, stop);
161
PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
162
const pj_timestamp *stop )
164
pj_highprec_t elapsed = elapsed_msec(start, stop);
165
pj_time_val tv_elapsed;
167
if (PJ_HIGHPREC_VALUE_IS_ZERO(elapsed)) {
168
tv_elapsed.sec = tv_elapsed.msec = 0;
171
pj_highprec_t sec, msec;
174
pj_highprec_div(sec, MSEC);
175
tv_elapsed.sec = (long)sec;
178
pj_highprec_mod(msec, MSEC);
179
tv_elapsed.msec = (long)msec;
185
PJ_DEF(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
186
const pj_timestamp *stop )
188
return stop->u32.lo - start->u32.lo;
191
PJ_DEF(pj_status_t) pj_gettickcount(pj_time_val *tv)
193
pj_timestamp ts, start;
196
if ((status = pj_get_timestamp(&ts)) != PJ_SUCCESS)
199
pj_set_timestamp32(&start, 0, 0);
200
*tv = pj_elapsed_time(&start, &ts);
205
#endif /* PJ_HAS_HIGH_RES_TIMER */