1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
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
30 #define u64tohighprec(u64) ((pj_highprec_t)((pj_int64_t)(u64)))
31
get_elapsed(const pj_timestamp * start,const pj_timestamp * stop)32 static pj_highprec_t get_elapsed( const pj_timestamp *start,
33 const pj_timestamp *stop )
34 {
35 #if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
36 return u64tohighprec(stop->u64 - start->u64);
37 #else
38 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;
47 #endif
48 }
49
elapsed_msec(const pj_timestamp * start,const pj_timestamp * stop)50 static 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;
79 }
80
elapsed_usec(const pj_timestamp * start,const pj_timestamp * stop)81 static 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 */
91 #if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
92 freq = u64tohighprec(ts_freq.u64);
93 #else
94 freq = ts_freq.u32.hi;
95 pj_highprec_mul(freq, U32MAX);
96 freq += ts_freq.u32.lo;
97 #endif
98
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
pj_elapsed_nanosec(const pj_timestamp * start,const pj_timestamp * stop)112 PJ_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 */
122 #if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
123 freq = u64tohighprec(ts_freq.u64);
124 #else
125 freq = ts_freq.u32.hi;
126 pj_highprec_mul(freq, U32MAX);
127 freq += ts_freq.u32.lo;
128 #endif
129
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
pj_elapsed_usec(const pj_timestamp * start,const pj_timestamp * stop)143 PJ_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
pj_elapsed_msec(const pj_timestamp * start,const pj_timestamp * stop)149 PJ_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
pj_elapsed_msec64(const pj_timestamp * start,const pj_timestamp * stop)155 PJ_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
pj_elapsed_time(const pj_timestamp * start,const pj_timestamp * stop)161 PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
162 const pj_timestamp *stop )
163 {
164 pj_highprec_t elapsed = elapsed_msec(start, stop);
165 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;
174 pj_highprec_div(sec, MSEC);
175 tv_elapsed.sec = (long)sec;
176
177 msec = elapsed;
178 pj_highprec_mod(msec, MSEC);
179 tv_elapsed.msec = (long)msec;
180
181 return tv_elapsed;
182 }
183 }
184
pj_elapsed_cycle(const pj_timestamp * start,const pj_timestamp * stop)185 PJ_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
pj_gettickcount(pj_time_val * tv)191 PJ_DEF(pj_status_t) pj_gettickcount(pj_time_val *tv)
192 {
193 pj_timestamp ts, start;
194 pj_status_t status;
195
196 if ((status = pj_get_timestamp(&ts)) != PJ_SUCCESS)
197 return status;
198
199 pj_set_timestamp32(&start, 0, 0);
200 *tv = pj_elapsed_time(&start, &ts);
201
202 return PJ_SUCCESS;
203 }
204
205 #endif /* PJ_HAS_HIGH_RES_TIMER */
206
207