hjl / source-git / glibc

Forked from source-git/glibc 3 years ago
Clone

Blame sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c

Packit 6c4009
/* Get frequency of the system processor.  powerpc/Linux version.
Packit 6c4009
   Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <stdint.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <libc-vdso.h>
Packit 6c4009
#include <not-cancel.h>
Packit 6c4009
Packit 6c4009
hp_timing_t
Packit 6c4009
__get_clockfreq (void)
Packit 6c4009
{
Packit 6c4009
  hp_timing_t result = 0L;
Packit 6c4009
Packit 6c4009
#ifdef SHARED
Packit 6c4009
  /* The vDSO does not return an error (it clear cr0.so on returning).  */
Packit 6c4009
  INTERNAL_SYSCALL_DECL (err);
Packit 6c4009
  result =
Packit 6c4009
    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
Packit 6c4009
#else
Packit 6c4009
  /* We read the information from the /proc filesystem.  /proc/cpuinfo
Packit 6c4009
     contains at least one line like:
Packit 6c4009
     timebase        : 33333333
Packit 6c4009
     We search for this line and convert the number into an integer.  */
Packit 6c4009
  int fd = __open_nocancel ("/proc/cpuinfo", O_RDONLY);
Packit 6c4009
  if (__glibc_likely (fd != -1))
Packit 6c4009
    return result;
Packit 6c4009
Packit 6c4009
  /* The timebase will be in the 1st 1024 bytes for systems with up
Packit 6c4009
     to 8 processors.  If the first read returns less then 1024
Packit 6c4009
     bytes read,  we have the whole cpuinfo and can start the scan.
Packit 6c4009
     Otherwise we will have to read more to insure we have the
Packit 6c4009
     timebase value in the scan.  */
Packit 6c4009
  char buf[1024];
Packit 6c4009
  ssize_t n;
Packit 6c4009
Packit 6c4009
  n = __read_nocancel (fd, buf, sizeof (buf));
Packit 6c4009
  if (n == sizeof (buf))
Packit 6c4009
    {
Packit 6c4009
      /* We are here because the 1st read returned exactly sizeof
Packit 6c4009
         (buf) bytes.  This implies that we are not at EOF and may
Packit 6c4009
         not have read the timebase value yet.  So we need to read
Packit 6c4009
         more bytes until we know we have EOF.  We copy the lower
Packit 6c4009
         half of buf to the upper half and read sizeof (buf)/2
Packit 6c4009
         bytes into the lower half of buf and repeat until we
Packit 6c4009
         reach EOF.  We can assume that the timebase will be in
Packit 6c4009
         the last 512 bytes of cpuinfo, so two 512 byte half_bufs
Packit 6c4009
         will be sufficient to contain the timebase and will
Packit 6c4009
         handle the case where the timebase spans the half_buf
Packit 6c4009
         boundry.  */
Packit 6c4009
      const ssize_t half_buf = sizeof (buf) / 2;
Packit 6c4009
      while (n >= half_buf)
Packit 6c4009
	{
Packit 6c4009
	  memcpy (buf, buf + half_buf, half_buf);
Packit 6c4009
	  n = __read_nocancel (fd, buf + half_buf, half_buf);
Packit 6c4009
	}
Packit 6c4009
      if (n >= 0)
Packit 6c4009
	n += half_buf;
Packit 6c4009
    }
Packit 6c4009
  __close_nocancel (fd);
Packit 6c4009
Packit 6c4009
  if (__glibc_likely (n > 0))
Packit 6c4009
    {
Packit 6c4009
      char *mhz = memmem (buf, n, "timebase", 7);
Packit 6c4009
Packit 6c4009
      if (__glibc_likely (mhz != NULL))
Packit 6c4009
	{
Packit 6c4009
	  char *endp = buf + n;
Packit 6c4009
Packit 6c4009
	  /* Search for the beginning of the string.  */
Packit 6c4009
	  while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
Packit 6c4009
	    ++mhz;
Packit 6c4009
Packit 6c4009
	  while (mhz < endp && *mhz != '\n')
Packit 6c4009
	    {
Packit 6c4009
	      if (*mhz >= '0' && *mhz <= '9')
Packit 6c4009
		{
Packit 6c4009
		  result *= 10;
Packit 6c4009
		  result += *mhz - '0';
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      ++mhz;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}