1 /* Get frequency of the system processor. i386/Linux version.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <ctype.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <libc-internal.h>
25
26 static
memmem(const void * a,size_t len1,const void * b,size_t len2)27 void *memmem (const void *a, size_t len1, const void *b, size_t len2)
28 {
29 char *end, *start;
30 char *ptr1, *ptr2;
31
32 if (len2 > len1)
33 return NULL;
34
35 start = (char *)a;
36 end = start + len1;
37
38 while (start < end)
39 {
40 size_t len = len2;
41 ptr1 = start;
42 ptr2 = (char *)b;
43 while (len > 0 && *ptr1++ == *ptr2++)
44 --len;
45 if (len == 0)
46 return start;
47 ++start;
48 }
49
50 return NULL;
51 }
52
53 hp_timing_t
__get_clockfreq(void)54 __get_clockfreq (void)
55 {
56 /* We read the information from the /proc filesystem. It contains at
57 least one line like
58 cpu MHz : 497.840237
59 or also
60 cpu MHz : 497.841
61 We search for this line and convert the number in an integer. */
62 static hp_timing_t result;
63 int fd;
64
65 /* If this function was called before, we know the result. */
66 if (result != 0)
67 return result;
68
69 fd = open ("/proc/cpuinfo", O_RDONLY);
70 if (__builtin_expect (fd != -1, 1))
71 {
72 /* XXX AFAIK the /proc filesystem can generate "files" only up
73 to a size of 4096 bytes. */
74 char buf[4096];
75 ssize_t n;
76
77 n = read (fd, buf, sizeof buf);
78 if (__builtin_expect (n, 1) > 0)
79 {
80 char *mhz = memmem (buf, n, "cpu MHz", 7);
81
82 if (__builtin_expect (mhz != NULL, 1))
83 {
84 char *endp = buf + n;
85 int seen_decpoint = 0;
86 int ndigits = 0;
87
88 /* Search for the beginning of the string. */
89 while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
90 ++mhz;
91
92 while (mhz < endp && *mhz != '\n')
93 {
94 if (*mhz >= '0' && *mhz <= '9')
95 {
96 result *= 10;
97 result += *mhz - '0';
98 if (seen_decpoint)
99 ++ndigits;
100 }
101 else if (*mhz == '.')
102 seen_decpoint = 1;
103
104 ++mhz;
105 }
106
107 /* Compensate for missing digits at the end. */
108 while (ndigits++ < 6)
109 result *= 10;
110 }
111 }
112
113 close (fd);
114 }
115
116 return result;
117 }
118