1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* $Header: /pjproject-0.3/pjlib/src/pj/os_timestamp_common.c 2 10/14/05 12:26a Bennylp $ */
/*
* $Log: /pjproject-0.3/pjlib/src/pj/os_timestamp_common.c $
*
* 2 10/14/05 12:26a Bennylp
* Finished error code framework, some fixes in ioqueue, etc. Pretty
* major.
*
* 1 10/09/05 2:56p Bennylp
* Created.
*
*/
#include <pj/os.h>
#include <pj/compat/high_precision.h>
#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
#define U32MAX (0xFFFFFFFFUL)
#define NANOSEC (1000000000UL)
#define USEC (1000000UL)
#define MSEC (1000)
static pj_highprec_t get_elapsed( const pj_timestamp *start,
const pj_timestamp *stop )
{
pj_highprec_t elapsed_hi, elapsed_lo;
elapsed_hi = stop->u32.hi - start->u32.hi;
elapsed_lo = stop->u32.lo - start->u32.lo;
/* elapsed_hi = elapsed_hi * U32MAX */
pj_highprec_mul(elapsed_hi, U32MAX);
return elapsed_hi + elapsed_lo;
}
static pj_highprec_t elapsed_usec( const pj_timestamp *start,
const pj_timestamp *stop )
{
pj_timestamp ts_freq;
pj_highprec_t freq, elapsed;
if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
return 0;
/* Convert frequency timestamp */
freq = ts_freq.u32.hi;
pj_highprec_mul(freq, U32MAX);
freq += ts_freq.u32.lo;
/* Avoid division by zero. */
if (freq == 0) freq = 1;
/* Get elapsed time in cycles. */
elapsed = get_elapsed(start, stop);
/* usec = elapsed * USEC / freq */
pj_highprec_mul(elapsed, USEC);
pj_highprec_div(elapsed, freq);
return elapsed;
}
PJ_DEF(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
const pj_timestamp *stop )
{
pj_timestamp ts_freq;
pj_highprec_t freq, elapsed;
if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
return 0;
/* Convert frequency timestamp */
freq = ts_freq.u32.hi;
pj_highprec_mul(freq, U32MAX);
freq += ts_freq.u32.lo;
/* Avoid division by zero. */
if (freq == 0) freq = 1;
/* Get elapsed time in cycles. */
elapsed = get_elapsed(start, stop);
/* usec = elapsed * USEC / freq */
pj_highprec_mul(elapsed, NANOSEC);
pj_highprec_div(elapsed, freq);
return (pj_uint32_t)elapsed;
}
PJ_DEF(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
const pj_timestamp *stop )
{
return (pj_uint32_t)elapsed_usec(start, stop);
}
PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
const pj_timestamp *stop )
{
pj_highprec_t elapsed = elapsed_usec(start, stop);
pj_time_val tv_elapsed;
if (PJ_HIGHPREC_VALUE_IS_ZERO(elapsed)) {
tv_elapsed.sec = tv_elapsed.msec = 0;
return tv_elapsed;
} else {
pj_highprec_t sec, msec;
sec = elapsed;
pj_highprec_div(sec, USEC);
tv_elapsed.sec = (long)sec;
msec = elapsed;
pj_highprec_mod(msec, USEC);
pj_highprec_div(msec, 1000);
tv_elapsed.msec = (long)msec;
return tv_elapsed;
}
}
PJ_DEF(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
const pj_timestamp *stop )
{
return stop->u32.lo - start->u32.lo;
}
#endif /* PJ_HAS_HIGH_RES_TIMER */
|