int
__get_nprocs ()
{
  /* XXX Here will come a test for the new system call.  */

  const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512;
  char *buffer = alloca (buffer_size);
  char *buffer_end = buffer + buffer_size;
  char *cp = buffer_end;
  char *re = buffer_end;
  int result = 1;

#ifdef O_CLOEXEC
  const int flags = O_RDONLY | O_CLOEXEC;
#else
  const int flags = O_RDONLY;
#endif
  /* The /proc/stat format is more uniform, use it by default.  */
  int fd = open_not_cancel_2 ("/proc/stat", flags);
  if (fd != -1)
    {
      result = 0;

      char *l;
      while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
	/* The current format of /proc/stat has all the cpu* entries
	   at the front.  We assume here that stays this way.  */
	if (strncmp (l, "cpu", 3) != 0)
	  break;
	else if (isdigit (l[3]))
	  ++result;

      close_not_cancel_no_status (fd);
    }
  else
    {
      fd = open_not_cancel_2 ("/proc/cpuinfo", flags);
      if (fd != -1)
	{
	  GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result);
	  close_not_cancel_no_status (fd);
	}
    }

  return result;
}
int
__get_nprocs ()
{
  char buffer[8192];
  int result = 1;

  /* XXX Here will come a test for the new system call.  */

  /* The /proc/stat format is more uniform, use it by default.  */
  FILE *fp = fopen ("/proc/stat", "rc");
  if (fp != NULL)
    {
      /* No threads use this stream.  */
      __fsetlocking (fp, FSETLOCKING_BYCALLER);

      result = 0;
      while (fgets_unlocked (buffer, sizeof (buffer), fp) != NULL)
	if (strncmp (buffer, "cpu", 3) == 0 && isdigit (buffer[3]))
	  ++result;

      fclose (fp);
    }
  else
    {
      fp = fopen ("/proc/cpuinfo", "rc");
      if (fp != NULL)
	{
	  /* No threads use this stream.  */
	  __fsetlocking (fp, FSETLOCKING_BYCALLER);
	  GET_NPROCS_PARSER (fp, buffer, result);
	  fclose (fp);
	}
    }

  return result;
}
Пример #3
0
int
__get_nprocs (void)
{
  static int cached_result = -1;
  static time_t timestamp;

  time_t now = time (NULL);
  time_t prev = timestamp;
  atomic_read_barrier ();
  if (now == prev && cached_result > -1)
    return cached_result;

  /* XXX Here will come a test for the new system call.  */

  const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512;
  char *buffer = alloca (buffer_size);
  char *buffer_end = buffer + buffer_size;
  char *cp = buffer_end;
  char *re = buffer_end;

  const int flags = O_RDONLY | O_CLOEXEC;
  int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags);
  char *l;
  int result = 0;
  if (fd != -1)
    {
      l = next_line (fd, buffer, &cp, &re, buffer_end);
      if (l != NULL)
	do
	  {
	    char *endp;
	    unsigned long int n = strtoul (l, &endp, 10);
	    if (l == endp)
	      {
		result = 0;
		break;
	      }

	    unsigned long int m = n;
	    if (*endp == '-')
	      {
		l = endp + 1;
		m = strtoul (l, &endp, 10);
		if (l == endp)
		  {
		    result = 0;
		    break;
		  }
	      }

	    result += m - n + 1;

	    l = endp;
	    while (l < re && isspace (*l))
	      ++l;
	  }
	while (l < re);

      __close_nocancel_nostatus (fd);

      if (result > 0)
	goto out;
    }

  cp = buffer_end;
  re = buffer_end;

  /* Default to an SMP system in case we cannot obtain an accurate
     number.  */
  result = 2;

  /* The /proc/stat format is more uniform, use it by default.  */
  fd = __open_nocancel ("/proc/stat", flags);
  if (fd != -1)
    {
      result = 0;

      while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
	/* The current format of /proc/stat has all the cpu* entries
	   at the front.  We assume here that stays this way.  */
	if (strncmp (l, "cpu", 3) != 0)
	  break;
	else if (isdigit (l[3]))
	  ++result;

      __close_nocancel_nostatus (fd);
    }
  else
    {
      fd = __open_nocancel ("/proc/cpuinfo", flags);
      if (fd != -1)
	{
	  GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result);
	  __close_nocancel_nostatus (fd);
	}
    }

 out:
  cached_result = result;
  atomic_write_barrier ();
  timestamp = now;

  return result;
}