blob: af5e493871ee5ce59689d237ccb48a2f53cb0735 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id: os_timestamp_common.c 3553 2011-05-05 06:14:19Z nanang $ */
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
32static 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
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;
79}
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 */
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
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 */
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
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
149PJ_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
155PJ_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
161PJ_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
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
191PJ_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