blob: 293f61622e43d98a0816285746f586cca95a0e29 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
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.
10 *
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.
15 *
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
19 */
20#include <pj/os.h>
21#include <pj/compat/high_precision.h>
22
23#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
24
25#define U32MAX (0xFFFFFFFFUL)
26#define NANOSEC (1000000000UL)
27#define USEC (1000000UL)
28#define MSEC (1000)
29
Benny Prijono99683ae2005-11-21 16:59:47 +000030#define u64tohighprec(u64) ((pj_highprec_t)((pj_int64_t)(u64)))
31
Benny Prijono9033e312005-11-21 02:08:39 +000032static pj_highprec_t get_elapsed( const pj_timestamp *start,
33 const pj_timestamp *stop )
34{
Benny Prijono99683ae2005-11-21 16:59:47 +000035#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
36 return u64tohighprec(stop->u64 - start->u64);
37#else
Benny Prijono9033e312005-11-21 02:08:39 +000038 pj_highprec_t elapsed_hi, elapsed_lo;
39
40 elapsed_hi = stop->u32.hi - start->u32.hi;
41 elapsed_lo = stop->u32.lo - start->u32.lo;
42
43 /* elapsed_hi = elapsed_hi * U32MAX */
44 pj_highprec_mul(elapsed_hi, U32MAX);
45
46 return elapsed_hi + elapsed_lo;
Benny Prijono99683ae2005-11-21 16:59:47 +000047#endif
48}
49
50static pj_highprec_t elapsed_msec( const pj_timestamp *start,
51 const pj_timestamp *stop )
52{
53 pj_timestamp ts_freq;
54 pj_highprec_t freq, elapsed;
55
56 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
57 return 0;
58
59 /* Convert frequency timestamp */
60#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
61 freq = u64tohighprec(ts_freq.u64);
62#else
63 freq = ts_freq.u32.hi;
64 pj_highprec_mul(freq, U32MAX);
65 freq += ts_freq.u32.lo;
66#endif
67
68 /* Avoid division by zero. */
69 if (freq == 0) freq = 1;
70
71 /* Get elapsed time in cycles. */
72 elapsed = get_elapsed(start, stop);
73
74 /* usec = elapsed * MSEC / freq */
75 pj_highprec_mul(elapsed, MSEC);
76 pj_highprec_div(elapsed, freq);
77
78 return elapsed;
Benny Prijono9033e312005-11-21 02:08:39 +000079}
80
81static pj_highprec_t elapsed_usec( const pj_timestamp *start,
82 const pj_timestamp *stop )
83{
84 pj_timestamp ts_freq;
85 pj_highprec_t freq, elapsed;
86
87 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
88 return 0;
89
90 /* Convert frequency timestamp */
Benny Prijono99683ae2005-11-21 16:59:47 +000091#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
92 freq = u64tohighprec(ts_freq.u64);
93#else
Benny Prijono9033e312005-11-21 02:08:39 +000094 freq = ts_freq.u32.hi;
95 pj_highprec_mul(freq, U32MAX);
96 freq += ts_freq.u32.lo;
Benny Prijono99683ae2005-11-21 16:59:47 +000097#endif
Benny Prijono9033e312005-11-21 02:08:39 +000098
99 /* Avoid division by zero. */
100 if (freq == 0) freq = 1;
101
102 /* Get elapsed time in cycles. */
103 elapsed = get_elapsed(start, stop);
104
105 /* usec = elapsed * USEC / freq */
106 pj_highprec_mul(elapsed, USEC);
107 pj_highprec_div(elapsed, freq);
108
109 return elapsed;
110}
111
112PJ_DEF(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
113 const pj_timestamp *stop )
114{
115 pj_timestamp ts_freq;
116 pj_highprec_t freq, elapsed;
117
118 if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
119 return 0;
120
121 /* Convert frequency timestamp */
Benny Prijono99683ae2005-11-21 16:59:47 +0000122#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
123 freq = u64tohighprec(ts_freq.u64);
124#else
Benny Prijono9033e312005-11-21 02:08:39 +0000125 freq = ts_freq.u32.hi;
126 pj_highprec_mul(freq, U32MAX);
127 freq += ts_freq.u32.lo;
Benny Prijono99683ae2005-11-21 16:59:47 +0000128#endif
Benny Prijono9033e312005-11-21 02:08:39 +0000129
130 /* Avoid division by zero. */
131 if (freq == 0) freq = 1;
132
133 /* Get elapsed time in cycles. */
134 elapsed = get_elapsed(start, stop);
135
136 /* usec = elapsed * USEC / freq */
137 pj_highprec_mul(elapsed, NANOSEC);
138 pj_highprec_div(elapsed, freq);
139
140 return (pj_uint32_t)elapsed;
141}
142
143PJ_DEF(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
144 const pj_timestamp *stop )
145{
146 return (pj_uint32_t)elapsed_usec(start, stop);
147}
148
Benny Prijono99683ae2005-11-21 16:59:47 +0000149PJ_DEF(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
150 const pj_timestamp *stop )
151{
152 return (pj_uint32_t)elapsed_msec(start, stop);
153}
154
Benny Prijonof1a47b82009-03-30 18:22:16 +0000155PJ_DEF(pj_uint64_t) pj_elapsed_msec64(const pj_timestamp *start,
156 const pj_timestamp *stop )
157{
158 return (pj_uint64_t)elapsed_msec(start, stop);
159}
160
Benny Prijono9033e312005-11-21 02:08:39 +0000161PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
162 const pj_timestamp *stop )
163{
Benny Prijono99683ae2005-11-21 16:59:47 +0000164 pj_highprec_t elapsed = elapsed_msec(start, stop);
Benny Prijono9033e312005-11-21 02:08:39 +0000165 pj_time_val tv_elapsed;
166
167 if (PJ_HIGHPREC_VALUE_IS_ZERO(elapsed)) {
168 tv_elapsed.sec = tv_elapsed.msec = 0;
169 return tv_elapsed;
170 } else {
171 pj_highprec_t sec, msec;
172
173 sec = elapsed;
Benny Prijono99683ae2005-11-21 16:59:47 +0000174 pj_highprec_div(sec, MSEC);
Benny Prijono9033e312005-11-21 02:08:39 +0000175 tv_elapsed.sec = (long)sec;
176
177 msec = elapsed;
Benny Prijono99683ae2005-11-21 16:59:47 +0000178 pj_highprec_mod(msec, MSEC);
Benny Prijono9033e312005-11-21 02:08:39 +0000179 tv_elapsed.msec = (long)msec;
180
181 return tv_elapsed;
182 }
183}
184
185PJ_DEF(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
186 const pj_timestamp *stop )
187{
188 return stop->u32.lo - start->u32.lo;
189}
190
191#endif /* PJ_HAS_HIGH_RES_TIMER */
192