blob: ee94e6e804209da2584867309df0ab6653a6b99b [file] [log] [blame]
Benny Prijonodd859a62005-11-01 16:42:51 +00001/* $Header: /pjproject-0.3/pjlib/src/pj/os_timestamp_linux.c 4 10/29/05 10:27p Bennylp $ */
2/* $Log: /pjproject-0.3/pjlib/src/pj/os_timestamp_linux.c $
3 *
4 * 4 10/29/05 10:27p Bennylp
5 * Fixed misc warnings.
6 *
7 * 3 10/29/05 11:51a Bennylp
8 * Version 0.3-pre2.
9 *
10 * 2 9/21/05 1:39p Bennylp
11 * Periodic checkin for backup.
12 *
13 * 1 9/18/05 9:25p Bennylp
14 * Created.
15 *
16 */
17#include <pj/os.h>
18#include <pj/errno.h>
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <ctype.h>
23
24#if defined(PJ_HAS_PENTIUM) && PJ_HAS_PENTIUM!=0
25static int machine_speed_mhz;
26static pj_timestamp machine_speed;
27
28static __inline__ unsigned long long int rdtsc()
29{
30 unsigned long long int x;
31 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
32 return x;
33}
34
35/* Determine machine's CPU MHz to get the counter's frequency.
36 */
37static int get_machine_speed_mhz()
38{
39 FILE *strm;
40 char buf[512];
41 int len;
42 char *pos, *end;
43
44 PJ_CHECK_STACK();
45
46 /* Open /proc/cpuinfo and read the file */
47 strm = fopen("/proc/cpuinfo", "r");
48 if (!strm)
49 return -1;
50 len = fread(buf, 1, sizeof(buf), strm);
51 fclose(strm);
52 if (len < 1) {
53 return -1;
54 }
55 buf[len] = '\0';
56
57 /* Locate the MHz digit. */
58 pos = strstr(buf, "cpu MHz");
59 if (!pos)
60 return -1;
61 pos = strchr(pos, ':');
62 if (!pos)
63 return -1;
64 end = (pos += 2);
65 while (isdigit(*end)) ++end;
66 *end = '\0';
67
68 /* Return the Mhz part, and give it a +1. */
69 return atoi(pos)+1;
70}
71
72PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
73{
74 if (machine_speed_mhz == 0) {
75 machine_speed_mhz = get_machine_speed_mhz();
76 if (machine_speed_mhz > 0) {
77 machine_speed.u64 = machine_speed_mhz * 1000000.0;
78 }
79 }
80
81 if (machine_speed_mhz == -1) {
82 ts->u64 = 0;
83 return -1;
84 }
85 ts->u64 = rdtsc();
86 return 0;
87}
88
89PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
90{
91 if (machine_speed_mhz == 0) {
92 machine_speed_mhz = get_machine_speed_mhz();
93 if (machine_speed_mhz > 0) {
94 machine_speed.u64 = machine_speed_mhz * 1000000.0;
95 }
96 }
97
98 if (machine_speed_mhz == -1) {
99 freq->u64 = 1; /* return 1 to prevent division by zero in apps. */
100 return -1;
101 }
102
103 freq->u64 = machine_speed.u64;
104 return 0;
105}
106
107#else
108#include <sys/time.h>
109#include <errno.h>
110
111#define USEC_PER_SEC 1000000
112
113PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
114{
115 struct timeval tv;
116
117 if (gettimeofday(&tv, NULL) != 0) {
118 return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
119 }
120
121 ts->u64 = tv.tv_sec;
122 ts->u64 *= USEC_PER_SEC;
123 ts->u64 += tv.tv_usec;
124
125 return PJ_SUCCESS;
126}
127
128PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
129{
130 freq->u32.hi = 0;
131 freq->u32.lo = USEC_PER_SEC;
132
133 return PJ_SUCCESS;
134}
135
136#endif
137