about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/getsysstats.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
committerUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
commita334319f6530564d22e775935d9c91663623a1b4 (patch)
treeb5877475619e4c938e98757d518bb1e9cbead751 /sysdeps/unix/sysv/linux/getsysstats.c
parent0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff)
downloadglibc-a334319f6530564d22e775935d9c91663623a1b4.tar.gz
glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.xz
glibc-a334319f6530564d22e775935d9c91663623a1b4.zip
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'sysdeps/unix/sysv/linux/getsysstats.c')
-rw-r--r--sysdeps/unix/sysv/linux/getsysstats.c184
1 files changed, 145 insertions, 39 deletions
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
index d655ba3b27..985a0860cb 100644
--- a/sysdeps/unix/sysv/linux/getsysstats.c
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
@@ -1,5 +1,5 @@
 /* Determine various system internal values, Linux version.
-   Copyright (C) 1996-2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -34,6 +34,75 @@
 #include <atomic.h>
 
 
+/* The default value for the /proc filesystem mount point.  */
+static const char path_proc[] = "/proc";
+
+/* Actual mount point of /proc filesystem.  */
+libc_freeres_ptr (static char *mount_proc);
+
+/* Determine the path to the /proc filesystem if available.  */
+static const char *
+internal_function
+get_proc_path (char *buffer, size_t bufsize)
+{
+  struct mntent mount_point;
+  struct mntent *entry;
+  char *result = NULL;
+  char *copy_result;
+  FILE *fp;
+
+  /* First find the mount point of the proc filesystem.  */
+  fp = __setmntent (_PATH_MOUNTED, "r");
+  if (fp == NULL)
+    fp = __setmntent (_PATH_MNTTAB, "r");
+  if (fp != NULL)
+    {
+      /* We don't need locking.  */
+      (void) __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+      while ((entry = __getmntent_r (fp, &mount_point, buffer, bufsize))
+	     != NULL)
+	if (strcmp (mount_point.mnt_type, "proc") == 0)
+	  {
+	    result = mount_point.mnt_dir;
+	    break;
+	  }
+      __endmntent (fp);
+    }
+
+  /* If we haven't found anything this is generally a bad sign but we
+     handle it gracefully.  We return what is hopefully the right
+     answer (/proc) but we don't remember this.  This will enable
+     programs which started before the system is fully running to
+     adjust themselves.  */
+  if (result == NULL)
+    return path_proc;
+
+  /* Make a copy we can keep around.  */
+  copy_result = __strdup (result);
+  if (copy_result == NULL)
+    return result;
+
+  /* Now store the copied value.  But do it atomically.  */
+  assert (sizeof (long int) == sizeof (void *__unbounded));
+  if (atomic_compare_and_exchange_bool_acq (&mount_proc, copy_result, NULL))
+    /* Replacing the value failed.  This means another thread was
+       faster and we don't need the copy anymore.  */
+    free (copy_result);
+#if __BOUNDED_POINTERS__
+  else
+    {
+      /* compare_and_swap only copied the pointer value, so we must
+	 now copy the bounds as well.  */
+      __ptrlow (mount_proc) = __ptrlow (copy_result);
+      __ptrhigh (mount_proc) = __ptrhigh (copy_result);
+    }
+#endif
+
+  return mount_proc;
+}
+
+
 /* How we can determine the number of available processors depends on
    the configuration.  There is currently (as of version 2.0.21) no
    system call to determine the number.  It is planned for the 2.1.x
@@ -67,35 +136,50 @@
 int
 __get_nprocs ()
 {
+  FILE *fp;
   char buffer[8192];
+  const char *proc_path;
   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)
+  /* Get mount point of proc filesystem.  */
+  proc_path = get_proc_path (buffer, sizeof buffer);
+
+  /* If we haven't found an appropriate entry return 1.  */
+  if (proc_path != NULL)
     {
-      /* No threads use this stream.  */
-      __fsetlocking (fp, FSETLOCKING_BYCALLER);
+      char *proc_fname = alloca (strlen (proc_path) + sizeof ("/cpuinfo"));
 
-      result = 0;
-      while (fgets_unlocked (buffer, sizeof (buffer), fp) != NULL)
-	if (strncmp (buffer, "cpu", 3) == 0 && isdigit (buffer[3]))
-	  ++result;
+      /* The /proc/stat format is more uniform, use it by default.  */
+      __stpcpy (__stpcpy (proc_fname, proc_path), "/stat");
 
-      fclose (fp);
-    }
-  else
-    {
-      fp = fopen ("/proc/cpuinfo", "rc");
+      fp = fopen (proc_fname, "rc");
       if (fp != NULL)
 	{
 	  /* No threads use this stream.  */
 	  __fsetlocking (fp, FSETLOCKING_BYCALLER);
-	  GET_NPROCS_PARSER (fp, buffer, result);
+
+	  result = 0;
+	  while (fgets_unlocked (buffer, sizeof (buffer), fp) != NULL)
+	    if (strncmp (buffer, "cpu", 3) == 0 && isdigit (buffer[3]))
+	      ++result;
+
 	  fclose (fp);
 	}
+      else
+	{
+	  __stpcpy (__stpcpy (proc_fname, proc_path), "/cpuinfo");
+
+	  fp = fopen (proc_fname, "rc");
+	  if (fp != NULL)
+	    {
+	      /* No threads use this stream.  */
+	      __fsetlocking (fp, FSETLOCKING_BYCALLER);
+	      GET_NPROCS_PARSER (fp, buffer, result);
+	      fclose (fp);
+	    }
+	}
     }
 
   return result;
@@ -109,19 +193,30 @@ weak_alias (__get_nprocs, get_nprocs)
 int
 __get_nprocs_conf ()
 {
+  FILE *fp;
   char buffer[8192];
+  const char *proc_path;
   int result = 1;
 
   /* XXX Here will come a test for the new system call.  */
 
+  /* Get mount point of proc filesystem.  */
+  proc_path = get_proc_path (buffer, sizeof buffer);
+
   /* If we haven't found an appropriate entry return 1.  */
-  FILE *fp = fopen ("/proc/cpuinfo", "rc");
-  if (fp != NULL)
+  if (proc_path != NULL)
     {
-      /* No threads use this stream.  */
-      __fsetlocking (fp, FSETLOCKING_BYCALLER);
-      GET_NPROCS_CONF_PARSER (fp, buffer, result);
-      fclose (fp);
+      char *proc_cpuinfo = alloca (strlen (proc_path) + sizeof ("/cpuinfo"));
+      __stpcpy (__stpcpy (proc_cpuinfo, proc_path), "/cpuinfo");
+
+      fp = fopen (proc_cpuinfo, "rc");
+      if (fp != NULL)
+	{
+	  /* No threads use this stream.  */
+	  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+	  GET_NPROCS_CONF_PARSER (fp, buffer, result);
+	  fclose (fp);
+	}
     }
 
   return result;
@@ -140,29 +235,40 @@ static long int
 internal_function
 phys_pages_info (const char *format)
 {
+  FILE *fp;
   char buffer[8192];
+  const char *proc_path;
   long int result = -1;
 
+  /* Get mount point of proc filesystem.  */
+  proc_path = get_proc_path (buffer, sizeof buffer);
+
   /* If we haven't found an appropriate entry return 1.  */
-  FILE *fp = fopen ("/proc/meminfo", "rc");
-  if (fp != NULL)
+  if (proc_path != NULL)
     {
-      /* No threads use this stream.  */
-      __fsetlocking (fp, FSETLOCKING_BYCALLER);
-
-      result = 0;
-      /* Read all lines and count the lines starting with the
-	 string "processor".  We don't have to fear extremely long
-	 lines since the kernel will not generate them.  8192
-	 bytes are really enough.  */
-      while (fgets_unlocked (buffer, sizeof buffer, fp) != NULL)
-	if (sscanf (buffer, format, &result) == 1)
-	  {
-	    result /= (__getpagesize () / 1024);
-	    break;
-	  }
+      char *proc_meminfo = alloca (strlen (proc_path) + sizeof ("/meminfo"));
+      __stpcpy (__stpcpy (proc_meminfo, proc_path), "/meminfo");
 
-      fclose (fp);
+      fp = fopen (proc_meminfo, "rc");
+      if (fp != NULL)
+	{
+	  /* No threads use this stream.  */
+	  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+	  result = 0;
+	  /* Read all lines and count the lines starting with the
+	     string "processor".  We don't have to fear extremely long
+	     lines since the kernel will not generate them.  8192
+	     bytes are really enough.  */
+	  while (fgets_unlocked (buffer, sizeof buffer, fp) != NULL)
+	    if (sscanf (buffer, format, &result) == 1)
+	      {
+		result /= (__getpagesize () / 1024);
+		break;
+	      }
+
+	  fclose (fp);
+	}
     }
 
   if (result == -1)