r16111: Patch from Björn JACKE <samba@j3e.de>.
authorJames Peach <jpeach@samba.org>
Fri, 9 Jun 2006 01:02:54 +0000 (01:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:17:20 +0000 (11:17 -0500)
This fixes a problem where the clock definition for clock_gettime() is
present at compile time, but is not available on the running system. In
this case, we fall back to less-preferred clocks until we find one that
we can use.
(This used to be commit fc6ed6a1aa2225ccde04c4ecaf0777dc0de4f1cb)

source3/aclocal.m4
source3/configure.in
source3/profile/profile.c

index 8abecd216f031df7416eebb986726bdc1ad8b6cd..59bd26bd245a36907b220699bd99ce0153fe2a19 100644 (file)
@@ -839,10 +839,17 @@ dnl Test whether the current LIBS results in libpthread being present.
 dnl Execute the corresponding user action list.
 AC_DEFUN([SMB_IS_LIBPTHREAD_LINKED],
 [
+    AC_MSG_CHECKING(if libpthread is linked)
     AC_TRY_LINK([],
        [return pthread_create(0, 0, 0, 0);],
-       [$1],
-       [$2])
+       [
+           AC_MSG_RESULT(yes)
+           $1
+       ],
+       [
+           AC_MSG_RESULT(no)
+           $2
+       ])
 ])
 
 dnl SMB_REMOVE_LIB(lib)
@@ -943,3 +950,34 @@ void main(void) {
     fi
 
 ])
+
+dnl SMB_CHECK_CLOCK_ID(clockid)
+dnl Test whether the specified clock_gettime clock ID is available. If it
+dnl is, we define HAVE_clockid
+AC_DEFUN([SMB_CHECK_CLOCK_ID],
+[
+    AC_MSG_CHECKING(for $1)
+    AC_TRY_LINK([
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+    ],
+    [
+clockid_t clk = $1;
+    ],
+    [
+       AC_MSG_RESULT(yes)
+       AC_DEFINE(HAVE_$1, 1,
+           [Whether the clock_gettime clock ID $1 is available])
+    ],
+    [
+       AC_MSG_RESULT(no)
+    ])
+])
index f8eba2349f9c0cfb51686346f99acdb6ed498f85..799441ed950e5ecfce116fe9c94899382874c69c 100644 (file)
@@ -2053,8 +2053,13 @@ if test x"$samba_cv_WITH_PROFILE" = x"yes"; then
            [
                SMB_IS_LIBPTHREAD_LINKED(
                        [ SMB_REMOVELIB(rt) ],
-                       [ AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
-                           [Whether clock_gettime is available]) ])
+                       [
+                           AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
+                               [Whether clock_gettime is available])
+                           SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC)
+                           SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID)
+                           SMB_CHECK_CLOCK_ID(CLOCK_REALTIME)
+                       ])
            ])
 
 fi
index ba9596301c6491d3a25e615b34749c5a8d903337..b0db629682986d7a01b1cff6b902a8194dcded76 100644 (file)
@@ -30,6 +30,7 @@ static int shm_id;
 static BOOL read_only;
 #if defined(HAVE_CLOCK_GETTIME)
 clockid_t __profile_clock;
+BOOL have_profiling_clock = False;
 #endif
 #endif
 
@@ -62,6 +63,19 @@ void profile_message(int msg_type, struct process_id src, void *buf, size_t len)
                         (int)procid_to_pid(&src)));
                break;
        case 2:         /* turn on complete profiling */
+
+#if defined(HAVE_CLOCK_GETTIME)
+               if (!have_profiling_clock) {
+                       do_profile_flag = True;
+                       do_profile_times = False;
+                       DEBUG(1,("INFO: Profiling counts turned ON from "
+                               "pid %d\n", (int)procid_to_pid(&src)));
+                       DEBUGADD(1,("INFO: Profiling times disabled "
+                               "due to lack of a suitable clock\n"));
+                       break;
+               }
+#endif
+
                do_profile_flag = True;
                do_profile_times = True;
                DEBUG(1,("INFO: Full profiling turned ON from pid %d\n",
@@ -100,28 +114,74 @@ void reqprofile_message(int msg_type, struct process_id src,
   open the profiling shared memory area
   ******************************************************************/
 #ifdef WITH_PROFILE
+
+#ifdef HAVE_CLOCK_GETTIME
+
+/* Find a clock. Just because the definition for a particular clock ID is
+ * present doesn't mean the system actually supports it.
+ */
+static void init_clock_gettime(void)
+{
+       struct timespec ts;
+
+       have_profiling_clock = False;
+
+#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
+       /* CLOCK_PROCESS_CPUTIME_ID is sufficiently fast that the
+        * always profiling times is plausible. Unfortunately on Linux
+        * it is only accurate if we can guarantee we will not be scheduled
+        * scheduled onto a different CPU between samples. Until there is
+        * some way to set processor affinity, we can only use this on
+        * uniprocessors.
+        */
+       if (!this_is_smp()) {
+           if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
+                   DEBUG(10, ("Using CLOCK_PROCESS_CPUTIME_ID "
+                               "for profile_clock\n"));
+                   __profile_clock = CLOCK_PROCESS_CPUTIME_ID;
+                   have_profiling_clock = True;
+           }
+       }
+#endif
+
+#ifdef HAVE_CLOCK_MONOTONIC
+       if (!have_profiling_clock &&
+           clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+               DEBUG(10, ("Using CLOCK_MONOTONIC for profile_clock\n"));
+               __profile_clock = CLOCK_MONOTONIC;
+               have_profiling_clock = True;
+               return;
+       }
+#endif
+
+#ifdef HAVE_CLOCK_REALTIME
+       /* POSIX says that CLOCK_REALTIME should be defined everywhere
+        * where we have clock_gettime...
+        */
+       if (!have_profiling_clock &&
+           clock_gettime(CLOCK_REALTIME, &ts) == 0) {
+               __profile_clock = CLOCK_REALTIME;
+               have_profiling_clock = True;
+       }
+
+       SMB_WARN(__profile_clock == CLOCK_REALTIME,
+               ("Using (slow) CLOCK_REALTIME for profile_clock"));
+#endif
+
+       SMB_WARN(have_profiling_clock == False,
+               ("could not find a working clock for profiling"));
+       return have_profiling_clock;
+}
+#endif
+
 BOOL profile_setup(BOOL rdonly)
 {
        struct shmid_ds shm_ds;
 
        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;
-       }
+#ifdef HAVE_CLOCK_GETTIME
+       init_clock_gettime();
 #endif
 
  again: