By default the X server will try CLOCK_MONOTONIC_COARSE before CLOCK_MONOTONIC. This causes various issues for Wayland display servers who may get their internal timestamps from the CLOCK_MONOTONIC, since it may very well happen that a timestamp from CLOCK_MONOTONIC retrieved before a sending an X request will still be "later" than the timestamp the X server than gets after receiving the request, due to the fact that CLOCK_MONOTONIC_COARSE has a lower resolution.
To make it possible for Wayland display servers to have more control over the clock the X server uses, add a '-forceMonotonic' command line argument to Xwayland, that forces the X server to always use the CLOCK_MONOTONIC clock as its source for timestamps. This commit also makes it a build requirement to have clock_gettime() and CLOCK_MONOTONIC support, and a runtime requirement to have CLOCK_MONOTONIC support if the clock was forced to be monotonic. Signed-off-by: Jonas Ådahl <jad...@gmail.com> --- Hi, This patch fixes various issues[0] related to the race condition described in the commit message. An alternative solution discussed has been to allow a "grace period" as long as the clock resolution difference for future timestamps, or rounding down timestamps from CLOCK_MONOTONIC in the display server. I think both these solutions have their own problems, while just changing the clock here only has a (most likely negliable) performance loss. FWIW, I would be just as fine with always forcing CLOCK_MONOTONIC for Xwayland if the command line argument seems unnecessary. Jonas [0] https://bugzilla.gnome.org/show_bug.cgi?id=756272 configure.ac | 4 ++++ hw/xwayland/xwayland.c | 6 ++++++ include/os.h | 7 +++++++ os/utils.c | 26 ++++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index f4de90f..8cc508c 100644 --- a/configure.ac +++ b/configure.ac @@ -2471,6 +2471,10 @@ if test "x$XWAYLAND" = xyes; then AC_SUBST([XWAYLAND_LIBS]) AC_SUBST([XWAYLAND_SYS_LIBS]) + if test "x$MONOTONIC_CLOCK" != xyes; then + AC_MSG_ERROR([Xwayland requires CLOCK_MONOTONIC support.]) + fi + WAYLAND_PREFIX=`$PKG_CONFIG --variable=prefix wayland-client` AC_PATH_PROG([WAYLAND_SCANNER], [wayland-scanner],, [${WAYLAND_PREFIX}/bin$PATH_SEPARATOR$PATH]) diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 3d36205..fa0143e 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -32,6 +32,7 @@ #include <misyncshm.h> #include <compositeext.h> #include <glx_extinit.h> +#include <os.h> void ddxGiveUp(enum ExitCode error) @@ -68,6 +69,7 @@ ddxUseMsg(void) ErrorF("-rootless run rootless, requires wm support\n"); ErrorF("-wm fd create X client for wm on given fd\n"); ErrorF("-listen fd add give fd as a listen socket\n"); + ErrorF("-forceMonotonic force usage of CLOCK_MONOTONIC\n"); } int @@ -86,6 +88,10 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (strcmp(argv[i], "-shm") == 0) { return 1; } + else if (strcmp(argv[i], "-forceMonotonic") == 0) { + ForceClockId(CLOCK_MONOTONIC); + return 1; + } return 0; } diff --git a/include/os.h b/include/os.h index 461d5d6..f37ad5d 100644 --- a/include/os.h +++ b/include/os.h @@ -51,6 +51,9 @@ SOFTWARE. #include <stdarg.h> #include <stdint.h> #include <string.h> +#ifdef MONOTONIC_CLOCK +#include <time.h> +#endif #define SCREEN_SAVER_ON 0 #define SCREEN_SAVER_OFF 1 @@ -180,6 +183,10 @@ extern _X_EXPORT void ListenOnOpenFD(int /* fd */ , int /* noxauth */ ); extern _X_EXPORT Bool AddClientOnOpenFD(int /* fd */ ); +#ifdef MONOTONIC_CLOCK +extern _X_EXPORT void ForceClockId(clockid_t /* forced_clockid */); +#endif + extern _X_EXPORT CARD32 GetTimeInMillis(void); extern _X_EXPORT CARD64 GetTimeInMicros(void); diff --git a/os/utils.c b/os/utils.c index e48d9f8..85e7b07 100644 --- a/os/utils.c +++ b/os/utils.c @@ -210,6 +210,10 @@ sig_atomic_t inSignalContext = FALSE; #define HAS_SAVED_IDS_AND_SETEUID #endif +#ifdef MONOTONIC_CLOCK +static clockid_t clockid; +#endif + OsSigHandlerPtr OsSignal(int sig, OsSigHandlerPtr handler) { @@ -427,6 +431,26 @@ GiveUp(int sig) errno = olderrno; } +#ifdef MONOTONIC_CLOCK +void +ForceClockId(clockid_t forced_clockid) +{ + struct timespec tp; + + if (clockid) { + ErrorF("Warning: clock id was forced after it was initialized.\n"); + return; + } + clockid = forced_clockid; + + if (clock_gettime(clockid, &tp) != 0) { + FatalError("Forced clock id failed to retrieve current time: %s\n", + strerror(errno)); + return; + } +} +#endif + #if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__) CARD32 GetTimeInMillis(void) @@ -446,7 +470,6 @@ GetTimeInMillis(void) #ifdef MONOTONIC_CLOCK struct timespec tp; - static clockid_t clockid; if (!clockid) { #ifdef CLOCK_MONOTONIC_COARSE @@ -475,7 +498,6 @@ GetTimeInMicros(void) struct timeval tv; #ifdef MONOTONIC_CLOCK struct timespec tp; - static clockid_t clockid; if (!clockid) { if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) -- 2.4.3 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel