Add sudo_gettime_uptime() to measure time while not sleeping.

This commit is contained in:
Todd C. Miller
2018-08-19 09:55:08 -06:00
parent e74d7e8721
commit b3227d3ed5
7 changed files with 245 additions and 37 deletions

114
aclocal.m4 vendored
View File

@@ -12,6 +12,120 @@
# PARTICULAR PURPOSE. # PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
# longlong.m4 serial 17
dnl Copyright (C) 1999-2007, 2009-2016 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Paul Eggert.
# Define HAVE_LONG_LONG_INT if 'long long int' works.
# This fixes a bug in Autoconf 2.61, and can be faster
# than what's in Autoconf 2.62 through 2.68.
# Note: If the type 'long long int' exists but is only 32 bits large
# (as on some very old compilers), HAVE_LONG_LONG_INT will not be
# defined. In this case you can treat 'long long int' like 'long int'.
AC_DEFUN([AC_TYPE_LONG_LONG_INT],
[
AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int],
[ac_cv_type_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
if test $ac_cv_type_long_long_int = yes; then
dnl Catch a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004.
dnl If cross compiling, assume the bug is not important, since
dnl nobody cross compiles for this platform as far as we know.
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[@%:@include <limits.h>
@%:@ifndef LLONG_MAX
@%:@ define HALF \
(1LL << (sizeof (long long int) * CHAR_BIT - 2))
@%:@ define LLONG_MAX (HALF - 1 + HALF)
@%:@endif]],
[[long long int n = 1;
int i;
for (i = 0; ; i++)
{
long long int m = n << i;
if (m >> i != n)
return 1;
if (LLONG_MAX / 2 < m)
break;
}
return 0;]])],
[],
[ac_cv_type_long_long_int=no],
[:])
fi
fi])
if test $ac_cv_type_long_long_int = yes; then
AC_DEFINE([HAVE_LONG_LONG_INT], [1],
[Define to 1 if the system has the type 'long long int'.])
fi
])
# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works.
# This fixes a bug in Autoconf 2.61, and can be faster
# than what's in Autoconf 2.62 through 2.68.
# Note: If the type 'unsigned long long int' exists but is only 32 bits
# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT
# will not be defined. In this case you can treat 'unsigned long long int'
# like 'unsigned long int'.
AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
[
AC_CACHE_CHECK([for unsigned long long int],
[ac_cv_type_unsigned_long_long_int],
[ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
AC_LINK_IFELSE(
[_AC_TYPE_LONG_LONG_SNIPPET],
[],
[ac_cv_type_unsigned_long_long_int=no])
fi])
if test $ac_cv_type_unsigned_long_long_int = yes; then
AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1],
[Define to 1 if the system has the type 'unsigned long long int'.])
fi
])
# Expands to a C program that can be used to test for simultaneous support
# of 'long long' and 'unsigned long long'. We don't want to say that
# 'long long' is available if 'unsigned long long' is not, or vice versa,
# because too many programs rely on the symmetry between signed and unsigned
# integer types (excluding 'bool').
AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
[
AC_LANG_PROGRAM(
[[/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;]],
[[/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));]])
])
m4_include([m4/ax_append_flag.m4]) m4_include([m4/ax_append_flag.m4])
m4_include([m4/ax_check_compile_flag.m4]) m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_link_flag.m4]) m4_include([m4/ax_check_link_flag.m4])

View File

@@ -470,7 +470,7 @@
/* Define to 1 if you have the <login_cap.h> header file. */ /* Define to 1 if you have the <login_cap.h> header file. */
#undef HAVE_LOGIN_CAP_H #undef HAVE_LOGIN_CAP_H
/* Define to 1 if the system has the type `long long int'. */ /* Define to 1 if the system has the type 'long long int'. */
#undef HAVE_LONG_LONG_INT #undef HAVE_LONG_LONG_INT
/* Define to 1 if you have the `lrand48' function. */ /* Define to 1 if you have the `lrand48' function. */
@@ -479,6 +479,9 @@
/* Define to 1 if you have the <machine/endian.h> header file. */ /* Define to 1 if you have the <machine/endian.h> header file. */
#undef HAVE_MACHINE_ENDIAN_H #undef HAVE_MACHINE_ENDIAN_H
/* Define to 1 if you have the `mach_continuous_time' function. */
#undef HAVE_MACH_CONTINUOUS_TIME
/* Define to 1 if you have the <maillock.h> header file. */ /* Define to 1 if you have the <maillock.h> header file. */
#undef HAVE_MAILLOCK_H #undef HAVE_MAILLOCK_H
@@ -860,7 +863,7 @@
/* Define to 1 if you have the `unsetenv' function. */ /* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV #undef HAVE_UNSETENV
/* Define to 1 if the system has the type `unsigned long long int'. */ /* Define to 1 if the system has the type 'unsigned long long int'. */
#undef HAVE_UNSIGNED_LONG_LONG_INT #undef HAVE_UNSIGNED_LONG_LONG_INT
/* Define to 1 if you have the <util.h> header file. */ /* Define to 1 if you have the <util.h> header file. */

67
configure vendored
View File

@@ -16279,6 +16279,19 @@ done
fi fi
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES" RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Mach monotonic timer that runs while sleeping
for ac_func in mach_continuous_time
do :
ac_fn_c_check_func "$LINENO" "mach_continuous_time" "ac_cv_func_mach_continuous_time"
if test "x$ac_cv_func_mach_continuous_time" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_MACH_CONTINUOUS_TIME 1
_ACEOF
fi
done
# Undocumented API that dynamically allocates the groups. # Undocumented API that dynamically allocates the groups.
for ac_func in getgrouplist_2 for ac_func in getgrouplist_2
do : do :
@@ -18232,18 +18245,18 @@ else
/* end confdefs.h. */ /* end confdefs.h. */
/* For now, do not test the preprocessor; as of 2007 there are too many /* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */ #if to work with literals wider than 32 bits. */
/* Test literals. */ /* Test literals. */
long long int ll = 9223372036854775807ll; long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL; long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL; unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */ /* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)]; ? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)]; ? 1 : -1)];
int i = 63; int i = 63;
int int
main () main ()
@@ -18252,9 +18265,9 @@ main ()
long long int llmax = 9223372036854775807ll; long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull; unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll) | (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull)); | (ullmax / ull) | (ullmax % ull));
; ;
return 0; return 0;
} }
@@ -18286,33 +18299,33 @@ if ${ac_cv_type_long_long_int+:} false; then :
else else
ac_cv_type_long_long_int=yes ac_cv_type_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then if test "x${ac_cv_prog_cc_c99-no}" = xno; then
ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
if test $ac_cv_type_long_long_int = yes; then if test $ac_cv_type_long_long_int = yes; then
if test "$cross_compiling" = yes; then : if test "$cross_compiling" = yes; then :
: :
else else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
#include <limits.h> #include <limits.h>
#ifndef LLONG_MAX #ifndef LLONG_MAX
# define HALF \ # define HALF \
(1LL << (sizeof (long long int) * CHAR_BIT - 2)) (1LL << (sizeof (long long int) * CHAR_BIT - 2))
# define LLONG_MAX (HALF - 1 + HALF) # define LLONG_MAX (HALF - 1 + HALF)
#endif #endif
int int
main () main ()
{ {
long long int n = 1; long long int n = 1;
int i; int i;
for (i = 0; ; i++) for (i = 0; ; i++)
{ {
long long int m = n << i; long long int m = n << i;
if (m >> i != n) if (m >> i != n)
return 1; return 1;
if (LLONG_MAX / 2 < m) if (LLONG_MAX / 2 < m)
break; break;
} }
return 0; return 0;
; ;
return 0; return 0;
} }
@@ -18326,7 +18339,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext conftest.$ac_objext conftest.beam conftest.$ac_ext
fi fi
fi fi
fi fi
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5

View File

@@ -2215,6 +2215,9 @@ case "$host" in
fi fi
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES" RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Mach monotonic timer that runs while sleeping
AC_CHECK_FUNCS([mach_continuous_time])
# Undocumented API that dynamically allocates the groups. # Undocumented API that dynamically allocates the groups.
AC_CHECK_FUNCS([getgrouplist_2], [AC_CHECK_DECLS([getgrouplist_2])]) AC_CHECK_FUNCS([getgrouplist_2], [AC_CHECK_DECLS([getgrouplist_2])])

View File

@@ -170,6 +170,8 @@ __dso_public char *sudo_gethostname_v1(void);
#define sudo_gethostname() sudo_gethostname_v1() #define sudo_gethostname() sudo_gethostname_v1()
/* gettime.c */ /* gettime.c */
__dso_public int sudo_gettime_awake_v1(struct timespec *ts);
#define sudo_gettime_awake(_a) sudo_gettime_awake_v1((_a))
__dso_public int sudo_gettime_mono_v1(struct timespec *ts); __dso_public int sudo_gettime_mono_v1(struct timespec *ts);
#define sudo_gettime_mono(_a) sudo_gettime_mono_v1((_a)) #define sudo_gettime_mono(_a) sudo_gettime_mono_v1((_a))
__dso_public int sudo_gettime_real_v1(struct timespec *ts); __dso_public int sudo_gettime_real_v1(struct timespec *ts);

View File

@@ -34,13 +34,25 @@
#include "sudo_debug.h" #include "sudo_debug.h"
#include "sudo_util.h" #include "sudo_util.h"
/* On Linux, CLOCK_MONOTONIC does not run while suspended. */ /*
* On Linux and FreeBSD, CLOCK_MONOTONIC does not run while sleeping.
* Linux provides CLOCK_BOOTTIME which runs while sleeping (FreeBSD does not).
* Some systems provide CLOCK_UPTIME which only runs while awake.
*/
#if defined(CLOCK_BOOTTIME) #if defined(CLOCK_BOOTTIME)
# define SUDO_CLOCK_MONOTONIC CLOCK_BOOTTIME # define SUDO_CLOCK_BOOTTIME CLOCK_BOOTTIME
#elif defined(CLOCK_MONOTONIC) #elif defined(CLOCK_MONOTONIC)
# define SUDO_CLOCK_MONOTONIC CLOCK_MONOTONIC # define SUDO_CLOCK_BOOTTIME CLOCK_MONOTONIC
#endif
#if defined(CLOCK_UPTIME)
# define SUDO_CLOCK_AWAKE CLOCK_UPTIME
#elif defined(CLOCK_MONOTONIC)
# define SUDO_CLOCK_AWAKE CLOCK_MONOTONIC
#endif #endif
/*
* Wall clock time, may run backward.
*/
#if defined(HAVE_CLOCK_GETTIME) #if defined(HAVE_CLOCK_GETTIME)
int int
sudo_gettime_real_v1(struct timespec *ts) sudo_gettime_real_v1(struct timespec *ts)
@@ -72,24 +84,28 @@ sudo_gettime_real_v1(struct timespec *ts)
} }
#endif #endif
#if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_MONOTONIC) /*
* Monotonic time, only runs forward.
* We use a timer that only increments while sleeping, if possible.
*/
#if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_BOOTTIME)
int int
sudo_gettime_mono_v1(struct timespec *ts) sudo_gettime_mono_v1(struct timespec *ts)
{ {
static int has_monoclock = -1; static int has_monoclock = -1;
debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL) debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL)
/* Check whether the kernel/libc actually supports CLOCK_MONOTONIC. */ /* Check whether the kernel/libc actually supports a monotonic clock. */
# ifdef _SC_MONOTONIC_CLOCK # ifdef _SC_MONOTONIC_CLOCK
if (has_monoclock == -1) if (has_monoclock == -1)
has_monoclock = sysconf(_SC_MONOTONIC_CLOCK) != -1; has_monoclock = sysconf(_SC_MONOTONIC_CLOCK) != -1;
# endif # endif
if (!has_monoclock) if (!has_monoclock)
debug_return_int(sudo_gettime_real(ts)); debug_return_int(sudo_gettime_real(ts));
if (clock_gettime(SUDO_CLOCK_MONOTONIC, ts) == -1) { if (clock_gettime(SUDO_CLOCK_BOOTTIME, ts) == -1) {
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"clock_gettime(%d) failed, using wall clock", "clock_gettime(%d) failed, using wall clock",
(int)SUDO_CLOCK_MONOTONIC); (int)SUDO_CLOCK_BOOTTIME);
has_monoclock = 0; has_monoclock = 0;
debug_return_int(sudo_gettime_real(ts)); debug_return_int(sudo_gettime_real(ts));
} }
@@ -105,7 +121,11 @@ sudo_gettime_mono_v1(struct timespec *ts)
if (timebase_info.denom == 0) if (timebase_info.denom == 0)
(void) mach_timebase_info(&timebase_info); (void) mach_timebase_info(&timebase_info);
abstime = mach_absolute_time(); #ifdef HAVE_MACH_CONTINUOUS_TIME
abstime = mach_continuous_time(); /* runs while asleep */
#else
abstime = mach_absolute_time(); /* doesn't run while asleep */
#endif
nsec = abstime * timebase_info.numer / timebase_info.denom; nsec = abstime * timebase_info.numer / timebase_info.denom;
ts->tv_sec = nsec / 1000000000; ts->tv_sec = nsec / 1000000000;
ts->tv_nsec = nsec % 1000000000; ts->tv_nsec = nsec % 1000000000;
@@ -119,3 +139,55 @@ sudo_gettime_mono_v1(struct timespec *ts)
return sudo_gettime_real(ts); return sudo_gettime_real(ts);
} }
#endif #endif
/*
* Monotonic time, only runs forward.
* We use a timer that only increments while awake, if possible.
*/
#if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_AWAKE)
int
sudo_gettime_awake_v1(struct timespec *ts)
{
static int has_monoclock = -1;
debug_decl(sudo_gettime_awake, SUDO_DEBUG_UTIL)
/* Check whether the kernel/libc actually supports a monotonic clock. */
# ifdef _SC_MONOTONIC_CLOCK
if (has_monoclock == -1)
has_monoclock = sysconf(_SC_MONOTONIC_CLOCK) != -1;
# endif
if (!has_monoclock)
debug_return_int(sudo_gettime_real(ts));
if (clock_gettime(SUDO_CLOCK_AWAKE, ts) == -1) {
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"clock_gettime(%d) failed, using wall clock",
(int)SUDO_CLOCK_AWAKE);
has_monoclock = 0;
debug_return_int(sudo_gettime_real(ts));
}
debug_return_int(0);
}
#elif defined(__MACH__)
int
sudo_gettime_awake_v1(struct timespec *ts)
{
uint64_t abstime, nsec;
static mach_timebase_info_data_t timebase_info;
debug_decl(sudo_gettime_awake, SUDO_DEBUG_UTIL)
if (timebase_info.denom == 0)
(void) mach_timebase_info(&timebase_info);
abstime = mach_absolute_time();
nsec = abstime * timebase_info.numer / timebase_info.denom;
ts->tv_sec = nsec / 1000000000;
ts->tv_nsec = nsec % 1000000000;
debug_return_int(0);
}
#else
int
sudo_gettime_awake_v1(struct timespec *ts)
{
/* No monotonic uptime clock available, use wall clock. */
return sudo_gettime_real(ts);
}
#endif

View File

@@ -71,6 +71,7 @@ sudo_fatalx_nodebug_v1
sudo_get_ttysize_v1 sudo_get_ttysize_v1
sudo_getgrouplist2_v1 sudo_getgrouplist2_v1
sudo_gethostname_v1 sudo_gethostname_v1
sudo_gettime_awake_v1
sudo_gettime_mono_v1 sudo_gettime_mono_v1
sudo_gettime_real_v1 sudo_gettime_real_v1
sudo_lbuf_append_quoted_v1 sudo_lbuf_append_quoted_v1