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