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