blob: a86c174628a00cc7909b587212aa7203621e9c88 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/os.h>
20#include <pj/compat/high_precision.h>
21
22#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
23
24#define U32MAX (0xFFFFFFFFUL)
25#define NANOSEC (1000000000UL)
26#define USEC (1000000UL)
27#define MSEC (1000)
28
Benny Prijono99683ae2005-11-21 16:59:47 +000029#define u64tohighprec(u64) ((pj_highprec_t)((pj_int64_t)(u64)))
30
Benny Prijono9033e312005-11-21 02:08:39 +000031static pj_highprec_t get_elapsed( const pj_timestamp *start,
32 const pj_timestamp *stop )
33{
Benny Prijono99683ae2005-11-21 16:59:47 +000034#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
35 return u64tohighprec(stop->u64 - start->u64);
36#else
Benny Prijono9033e312005-11-21 02:08:39 +000037 pj_highprec_t elapsed_hi, elapsed_lo;
38
39 elapsed_hi = stop->u32.hi - start->u32.hi;
40 elapsed_lo = stop->u32.lo - start->u32.lo;
41
42 /* elapsed_hi = elapsed_hi * U32MAX */
43 pj_highprec_mul(elapsed_hi, U32MAX);
44
45 return elapsed_hi + elapsed_lo;
Benny Prijono99683ae2005-11-21 16:59:47 +000046#endif
47}
48
49static pj_highprec_t elapsed_msec( const pj_timestamp *start,
50 const pj_timestamp *stop )
51{
52 pj_timestamp ts_freq;
53 pj_highprec_t freq, elapsed;
54
55 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
56 return 0;
57
58 /* Convert frequency timestamp */
59#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
60 freq = u64tohighprec(ts_freq.u64);
61#else
62 freq = ts_freq.u32.hi;
63 pj_highprec_mul(freq, U32MAX);
64 freq += ts_freq.u32.lo;
65#endif
66
67 /* Avoid division by zero. */
68 if (freq == 0) freq = 1;
69
70 /* Get elapsed time in cycles. */
71 elapsed = get_elapsed(start, stop);
72
73 /* usec = elapsed * MSEC / freq */
74 pj_highprec_mul(elapsed, MSEC);
75 pj_highprec_div(elapsed, freq);
76
77 return elapsed;
Benny Prijono9033e312005-11-21 02:08:39 +000078}
79
80static pj_highprec_t elapsed_usec( const pj_timestamp *start,
81 const pj_timestamp *stop )
82{
83 pj_timestamp ts_freq;
84 pj_highprec_t freq, elapsed;
85
86 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
87 return 0;
88
89 /* Convert frequency timestamp */
Benny Prijono99683ae2005-11-21 16:59:47 +000090#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
91 freq = u64tohighprec(ts_freq.u64);
92#else
Benny Prijono9033e312005-11-21 02:08:39 +000093 freq = ts_freq.u32.hi;
94 pj_highprec_mul(freq, U32MAX);
95 freq += ts_freq.u32.lo;
Benny Prijono99683ae2005-11-21 16:59:47 +000096#endif
Benny Prijono9033e312005-11-21 02:08:39 +000097
98 /* Avoid division by zero. */
99 if (freq == 0) freq = 1;
100
101 /* Get elapsed time in cycles. */
102 elapsed = get_elapsed(start, stop);
103
104 /* usec = elapsed * USEC / freq */
105 pj_highprec_mul(elapsed, USEC);
106 pj_highprec_div(elapsed, freq);
107
108 return elapsed;
109}
110
111PJ_DEF(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
112 const pj_timestamp *stop )
113{
114 pj_timestamp ts_freq;
115 pj_highprec_t freq, elapsed;
116
117 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
118 return 0;
119
120 /* Convert frequency timestamp */
Benny Prijono99683ae2005-11-21 16:59:47 +0000121#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
122 freq = u64tohighprec(ts_freq.u64);
123#else
Benny Prijono9033e312005-11-21 02:08:39 +0000124 freq = ts_freq.u32.hi;
125 pj_highprec_mul(freq, U32MAX);
126 freq += ts_freq.u32.lo;
Benny Prijono99683ae2005-11-21 16:59:47 +0000127#endif
Benny Prijono9033e312005-11-21 02:08:39 +0000128
129 /* Avoid division by zero. */
130 if (freq == 0) freq = 1;
131
132 /* Get elapsed time in cycles. */
133 elapsed = get_elapsed(start, stop);
134
135 /* usec = elapsed * USEC / freq */
136 pj_highprec_mul(elapsed, NANOSEC);
137 pj_highprec_div(elapsed, freq);
138
139 return (pj_uint32_t)elapsed;
140}
141
142PJ_DEF(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
143 const pj_timestamp *stop )
144{
145 return (pj_uint32_t)elapsed_usec(start, stop);
146}
147
Benny Prijono99683ae2005-11-21 16:59:47 +0000148PJ_DEF(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
149 const pj_timestamp *stop )
150{
151 return (pj_uint32_t)elapsed_msec(start, stop);
152}
153
Benny Prijono9033e312005-11-21 02:08:39 +0000154PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
155 const pj_timestamp *stop )
156{
Benny Prijono99683ae2005-11-21 16:59:47 +0000157 pj_highprec_t elapsed = elapsed_msec(start, stop);
Benny Prijono9033e312005-11-21 02:08:39 +0000158 pj_time_val tv_elapsed;
159
160 if (PJ_HIGHPREC_VALUE_IS_ZERO(elapsed)) {
161 tv_elapsed.sec = tv_elapsed.msec = 0;
162 return tv_elapsed;
163 } else {
164 pj_highprec_t sec, msec;
165
166 sec = elapsed;
Benny Prijono99683ae2005-11-21 16:59:47 +0000167 pj_highprec_div(sec, MSEC);
Benny Prijono9033e312005-11-21 02:08:39 +0000168 tv_elapsed.sec = (long)sec;
169
170 msec = elapsed;
Benny Prijono99683ae2005-11-21 16:59:47 +0000171 pj_highprec_mod(msec, MSEC);
Benny Prijono9033e312005-11-21 02:08:39 +0000172 tv_elapsed.msec = (long)msec;
173
174 return tv_elapsed;
175 }
176}
177
178PJ_DEF(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
179 const pj_timestamp *stop )
180{
181 return stop->u32.lo - start->u32.lo;
182}
183
184#endif /* PJ_HAS_HIGH_RES_TIMER */
185