summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/getsysstats.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-06-22 09:50:39 -0400
committerUlrich Drepper <drepper@gmail.com>2011-06-22 09:50:39 -0400
commit852eb34d5c56bc75bdd82327fcf310d98655f6b0 (patch)
tree9fdcbffbbf1b1d40137a5a72904acbe941bf5634 /sysdeps/unix/sysv/linux/getsysstats.c
parent6e502e19455c6110dd4487d91b7b7d6d8121f9ba (diff)
downloadglibc-852eb34d5c56bc75bdd82327fcf310d98655f6b0.tar.gz
glibc-852eb34d5c56bc75bdd82327fcf310d98655f6b0.tar.xz
glibc-852eb34d5c56bc75bdd82327fcf310d98655f6b0.zip
Rate limit expensive _SC_NPROCESSORS_ONLN computation
Diffstat (limited to 'sysdeps/unix/sysv/linux/getsysstats.c')
-rw-r--r--sysdeps/unix/sysv/linux/getsysstats.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
index af454b650d..a13b6e3e37 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-2003,2006,2007,2009,2010 Free Software Foundation, Inc.
+   Copyright (C) 1996-2003,2006,2007,2009,2010,2011 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -35,6 +35,16 @@
 
 #include <atomic.h>
 #include <not-cancel.h>
+#include <kernel-features.h>
+
+#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+#else
+# include <bits/libc-vdso.h>
+#endif
 
 
 /* How we can determine the number of available processors depends on
@@ -128,6 +138,22 @@ next_line (int fd, char *const buffer, char **cp, char **re,
 int
 __get_nprocs ()
 {
+  static int cached_result;
+  static time_t timestamp;
+
+#ifdef __ASSUME_POSIX_TIMERS
+  struct timespec ts;
+  INTERNAL_SYSCALL_DECL (err);
+  INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts);
+#else
+  struct timeval ts;
+  gettimeofday (&ts, NULL);
+#endif
+  time_t prev = timestamp;
+  atomic_read_barrier ();
+  if (ts.tv_sec == prev)
+    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;
@@ -169,6 +195,10 @@ __get_nprocs ()
 	}
     }
 
+  cached_result = result;
+  atomic_write_barrier ();
+  timestamp = ts.tv_sec;
+
   return result;
 }
 weak_alias (__get_nprocs, get_nprocs)