From 8882d08b6ba90c45f8107eef3d28614eb643dfb9 Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 9 Jun 2006 01:02:54 +0000 Subject: [PATCH] =?UTF-8?q?r16111:=20Patch=20from=20Bj=C3=B6rn=20JACKE=20.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 | 42 +++++++++++++++++- source3/configure.in | 9 +++- source3/profile/profile.c | 92 ++++++++++++++++++++++++++++++++------- 3 files changed, 123 insertions(+), 20 deletions(-) diff --git a/source3/aclocal.m4 b/source3/aclocal.m4 index 8abecd216f0..59bd26bd245 100644 --- a/source3/aclocal.m4 +++ b/source3/aclocal.m4 @@ -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 +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# 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) + ]) +]) diff --git a/source3/configure.in b/source3/configure.in index f8eba2349f9..799441ed950 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -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 diff --git a/source3/profile/profile.c b/source3/profile/profile.c index ba9596301c6..b0db6296829 100644 --- a/source3/profile/profile.c +++ b/source3/profile/profile.c @@ -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: