summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/configure.in2
-rw-r--r--source3/include/smbprofile.h21
-rw-r--r--source3/lib/util.c18
-rw-r--r--source3/profile/profile.c21
-rw-r--r--source3/tdb/spinlock.c17
5 files changed, 62 insertions, 17 deletions
diff --git a/source3/configure.in b/source3/configure.in
index 40cf2d4a81..ca06afc08a 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -2019,6 +2019,8 @@ if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available])
fi
+AC_LIBTESTFUNC(rt, clock_gettime)
+
AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[
AC_TRY_LINK([#include <stdarg.h>
va_list ap1,ap2;], [va_copy(ap1,ap2);],
diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
index dd171ac13e..fb5fa078c1 100644
--- a/source3/include/smbprofile.h
+++ b/source3/include/smbprofile.h
@@ -419,6 +419,25 @@ extern BOOL do_profile_times;
#define DEC_PROFILE_COUNT(x) profile_p->x--
#define ADD_PROFILE_COUNT(x,y) profile_p->x += (y)
+#if defined(HAVE_CLOCK_GETTIME)
+
+extern clockid_t __profile_clock;
+
+static inline unsigned long long profile_timestamp(void)
+{
+ struct timespec ts;
+
+ /* FIXME: On a single-CPU system, or a system where we have bound
+ * daemon threads to single CPUs (eg. using cpusets or processor
+ * affinity), it might be preferable to use CLOCK_PROCESS_CPUTIME_ID.
+ */
+
+ clock_gettime(__profile_clock, &ts);
+ return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); /* usec */
+}
+
+#else
+
static inline unsigned long long profile_timestamp(void)
{
struct timeval tv;
@@ -426,6 +445,8 @@ static inline unsigned long long profile_timestamp(void)
return (tv.tv_sec * 1000000) + tv.tv_usec;
}
+#endif
+
/* end of helper macros */
#define DO_PROFILE_INC(x) \
diff --git a/source3/lib/util.c b/source3/lib/util.c
index a9aebd0822..fd48cbfa83 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2969,3 +2969,21 @@ BOOL procid_is_local(const struct process_id *pid)
{
return True;
}
+
+int this_is_smp(void)
+{
+#if defined(HAVE_SYSCONF)
+
+#if defined(SYSCONF_SC_NPROC_ONLN)
+ return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
+#elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
+ return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
+#else
+ return 0;
+#endif
+
+#else
+ return 0;
+#endif
+}
+
diff --git a/source3/profile/profile.c b/source3/profile/profile.c
index db8a643042..bacf00eb01 100644
--- a/source3/profile/profile.c
+++ b/source3/profile/profile.c
@@ -28,6 +28,9 @@
#ifdef WITH_PROFILE
static int shm_id;
static BOOL read_only;
+#if defined(HAVE_CLOCK_GETTIME)
+clockid_t __profile_clock;
+#endif
#endif
struct profile_header *profile_h;
@@ -103,6 +106,24 @@ BOOL profile_setup(BOOL rdonly)
read_only = rdonly;
+#if defined(HAVE_CLOCK_GETTIME)
+ if (this_is_smp()) {
+ /* This is faster that gettimeofday, but not fast enough to
+ * leave it enabled in production.
+ */
+ __profile_clock = CLOCK_MONOTONIC;
+ } else {
+ /* CLOCK_PROCESS_CPUTIME_ID is sufficiently fast that the
+ * always profiling times is plausible. Unfortunately it is
+ * only accurate if we can guarantee we will not be scheduled
+ * onto a different CPU between samples. Until there is some
+ * way to set processor affinity, we can only use this on
+ * uniprocessors.
+ */
+ __profile_clock = CLOCK_PROCESS_CPUTIME_ID;
+ }
+#endif
+
again:
/* try to use an existing key */
shm_id = shmget(PROF_SHMEM_KEY, 0, 0);
diff --git a/source3/tdb/spinlock.c b/source3/tdb/spinlock.c
index e6abb3a0bc..e42a6901c7 100644
--- a/source3/tdb/spinlock.c
+++ b/source3/tdb/spinlock.c
@@ -266,23 +266,6 @@ static void yield_cpu(void)
#endif
}
-static int this_is_smp(void)
-{
-#if defined(HAVE_SYSCONF)
-
-#if defined(SYSCONF_SC_NPROC_ONLN)
- return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
-#elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
- return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
-#else
- return 0;
-#endif
-
-#else
- return 0;
-#endif
-}
-
/*
* GENERIC
*/