[vlc-devel] [PATCH] compat: add clock_gettime, clock_nanosleep for darwin
Rémi Denis-Courmont
remi at remlab.net
Thu Feb 27 16:27:35 CET 2020
Hi,
- Using inline in a C file seems useless.
- Testing for cancellation on error other than EINTR is suspicious.
- Not sure LIBOBJ can be called conditionally.
Le 27 février 2020 16:56:01 GMT+02:00, Marvin Scholz <epirat07 at gmail.com> a écrit :
>---
> compat/clock_gettime.c | 131 +++++++++++++++++++++++++++++++++++++++
> compat/clock_nanosleep.c | 108 ++++++++++++++++++++++++++++++++
> configure.ac | 6 ++
> include/vlc_fixups.h | 18 ++++++
> 4 files changed, 263 insertions(+)
> create mode 100644 compat/clock_gettime.c
> create mode 100644 compat/clock_nanosleep.c
>
>diff --git a/compat/clock_gettime.c b/compat/clock_gettime.c
>new file mode 100644
>index 0000000000..fb3312fd2d
>--- /dev/null
>+++ b/compat/clock_gettime.c
>@@ -0,0 +1,131 @@
>+/*****************************************************************************
>+ * clock_gettime.c: POSIX clock_gettime() replacement
>+
>*****************************************************************************
>+ * Copyright © 2020 VLC authors and VideoLAN
>+ *
>+ * Author: Marvin Scholz <epirat07 at gmail dot com>
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify it
>+ * under the terms of the GNU Lesser General Public License as
>published by
>+ * the Free Software Foundation; either version 2.1 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>+
>*****************************************************************************/
>+
>+#ifndef __APPLE__
>+# error clock_gettime not implemented on your platform!
>+#endif
>+
>+#ifdef HAVE_CONFIG_H
>+# include <config.h>
>+#endif
>+
>+#define _DARWIN_C_SOURCE
>+#define _POSIX_C_SOURCE 200809L
>+
>+#include <sys/errno.h>
>+#include <sys/types.h>
>+#include <sys/time.h>
>+#include <sys/sysctl.h>
>+#include <time.h>
>+
>+/**
>+ * Get the absolute time at which the system was booted
>+ *
>+ * This time is changed whenever the clock is adjusted to
>+ * correctly reflect the boot time with the adjusted clock,
>+ * so just querying it once and reusing the value is not safe.
>+ *
>+ * \param[out] tv Timeval struct to write the boottime to
>+ *
>+ * \note
>+ * The boot time only has microsecond precision
>+ *
>+ * \return 0 on success, else -1 and errno set
>+ */
>+static inline int vlc__get_system_boottime(struct timeval *tv)
>+{
>+ int ret = sysctl((int[]){ CTL_KERN, KERN_BOOTTIME }, 2,
>+ tv, &(size_t){ sizeof(*tv) }, NULL, 0);
>+
>+ if (ret != 0)
>+ return errno;
>+
>+ return 0;
>+}
>+
>+/**
>+ * Get the monotonic time (CLOCK_MONOTONIC)
>+ *
>+ * Calculates a monotically incrasing time since system boot
>+ * that continues to increment when the syste is asleep.
>+ *
>+ * Warnings to everyone trying to simplify this:
>+ * - Using mach_continuous_time is not equivalent to this, see
>+ * the darwin manpage about CLOCK_MONOTONIC_RAW for an explanation.
>+ * - Using mach_absolute_time is not equivalent to this, as it does
>+ * not continue to increment when the system is asleep.
>+ * - The boot time is queried twice in a loop and only used if both
>+ * match. This is done to detect if the boot time change since we
>+ * obtained the current time of day, as the boot time can change
>+ * when the system wallclock is adjusted, as that will adjust the
>+ * boot time accordingly.
>+ *
>+ * \param[out] tv Timeval struct to write the monotonic time to
>+ *
>+ * \return 0 on success, else -1 and errno set
>+ */
>+static int vlc__get_monotonic(struct timeval *tv)
>+{
>+ int ret;
>+ struct timeval currenttime;
>+ struct timeval boottime_begin;
>+ struct timeval boottime_end;
>+
>+ do {
>+ ret = vlc__get_system_boottime(&boottime_begin);
>+ if (ret != 0)
>+ return ret;
>+
>+ ret = gettimeofday(¤ttime, NULL);
>+ if (ret != 0)
>+ return ret;
>+
>+ ret = vlc__get_system_boottime(&boottime_end);
>+ if (ret != 0)
>+ return ret;
>+ } while (timercmp(&boottime_begin, &boottime_end, !=));
>+
>+ timersub(¤ttime, &boottime_begin, tv);
>+ return 0;
>+}
>+
>+int clock_gettime(clockid_t clock_id, struct timespec *tp)
>+{
>+ int ret = 0;
>+ struct timeval tv;
>+
>+ switch (clock_id) {
>+ case CLOCK_MONOTONIC:
>+ ret = vlc__get_monotonic(&tv);
>+ break;
>+ case CLOCK_REALTIME:
>+ ret = gettimeofday(&tv, NULL);
>+ break;
>+ default:
>+ errno = EINVAL;
>+ return -1;
>+ }
>+
>+ if (ret == 0)
>+ TIMEVAL_TO_TIMESPEC(&tv, tp);
>+ return ret;
>+}
>diff --git a/compat/clock_nanosleep.c b/compat/clock_nanosleep.c
>new file mode 100644
>index 0000000000..f5cab11039
>--- /dev/null
>+++ b/compat/clock_nanosleep.c
>@@ -0,0 +1,108 @@
>+/*****************************************************************************
>+ * clock_nanosleep.c: POSIX clock_nanosleep() replacement
>+
>*****************************************************************************
>+ * Copyright © 2020 VLC authors and VideoLAN
>+ *
>+ * Author: Marvin Scholz <epirat07 at gmail dot com>
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify it
>+ * under the terms of the GNU Lesser General Public License as
>published by
>+ * the Free Software Foundation; either version 2.1 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>+
>*****************************************************************************/
>+
>+#ifndef __APPLE__
>+# error clock_nanosleep not implemented on your platform!
>+#endif
>+
>+#ifdef HAVE_CONFIG_H
>+# include <config.h>
>+#endif
>+
>+#define _DARWIN_C_SOURCE
>+#define _POSIX_C_SOURCE 200809L
>+
>+#include <pthread.h>
>+#include <sys/errno.h>
>+#include <sys/types.h>
>+#include <sys/time.h>
>+#include <sys/sysctl.h>
>+#include <mach/clock_types.h>
>+
>+#define timespecs_sub(tsa, tsb, tsr) \
>+ do { \
>+ (tsr)->tv_sec = (tsa)->tv_sec - (tsb)->tv_sec; \
>+ (tsr)->tv_nsec = (tsa)->tv_nsec - (tsb)->tv_nsec; \
>+ if ((tsr)->tv_nsec < 0) { \
>+ (tsr)->tv_sec--; \
>+ (tsr)->tv_nsec += NSEC_PER_SEC; \
>+ } \
>+ } while (0)
>+
>+#define timespec_zero(ts) \
>+ ((ts)->tv_sec == 0 && (ts)->tv_nsec == 0)
>+
>+int clock_nanosleep(clockid_t clock_id, int flags,
>+ const struct timespec *rqtp, struct timespec *rmtp)
>+{
>+ int err = EINVAL;
>+ struct timespec ts_rel;
>+
>+ // Validate timespec
>+ if (rqtp == NULL || rqtp->tv_sec < 0 ||
>+ rqtp->tv_nsec < 0 || (unsigned long)rqtp->tv_nsec >= NSEC_PER_SEC)
>+ goto error;
>+
>+ if (flags == TIMER_ABSTIME) {
>+ struct timespec ts_now;
>+
>+ // We don't support waiting for a absolute
>+ // wallclock time currently
>+ if (clock_id == CLOCK_REALTIME) {
>+ err = ENOTSUP;
>+ goto error;
>+ }
>+
>+ // Get current time with requested clock
>+ if (clock_gettime(clock_id, &ts_now) != 0) {
>+ err = errno;
>+ goto error;
>+ }
>+
>+ // Calculate relative timespec
>+ timespecs_sub(rqtp, &ts_now, &ts_rel);
>+
>+ // Check if time already elapsed
>+ if (ts_rel.tv_sec < 0 || timespec_zero(&ts_rel)) {
>+ pthread_testcancel();
>+ return 0;
>+ }
>+ } else if (flags == 0) {
>+ ts_rel = *rqtp;
>+ } else {
>+ // Invalid flags
>+ goto error;
>+ }
>+
>+ switch (clock_id) {
>+ case CLOCK_MONOTONIC:
>+ case CLOCK_REALTIME:
>+ return nanosleep(&ts_rel, rmtp);
>+ default:
>+ goto error;
>+ }
>+
>+error:
>+ pthread_testcancel();
>+ errno = err;
>+ return -1;
>+}
>diff --git a/configure.ac b/configure.ac
>index bc1874cb97..c20ab3c75c 100644
>--- a/configure.ac
>+++ b/configure.ac
>@@ -179,6 +179,12 @@ case "${host_os}" in
>VLC_ADD_LIBS([libvlc
>vlc],[-Wl,-undefined,dynamic_lookup,-framework,AppKit])
>VLC_ADD_LIBS([libvlccore],[-Wl,-framework,CoreFoundation,-framework,CoreServices])
>
>+ dnl macOS 10.11 lacks clock_gettime, introduced with 10.12
>+ AC_LIBOBJ([clock_gettime])
>+ dnl macOS lacks clock_nanosleep
>+ AC_LIBOBJ([clock_nanosleep])
>+ AC_CHECK_FUNCS([clock_gettime clock_nanosleep])
>+
> AC_EGREP_CPP(yes,
> [#import <TargetConditionals.h>
> #if TARGET_OS_IPHONE
>diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
>index 8fd01da0ce..a296db0c32 100644
>--- a/include/vlc_fixups.h
>+++ b/include/vlc_fixups.h
>@@ -658,6 +658,24 @@ FILE *vlc_win32_tmpfile(void);
>
> #ifdef __APPLE__
> # define fdatasync fsync
>+
>+# include <time.h>
>+# ifndef TIMER_ABSTIME
>+# define TIMER_ABSTIME 0x01
>+# endif
>+# ifndef CLOCK_REALTIME
>+# define CLOCK_REALTIME 0
>+# endif
>+# ifndef CLOCK_MONOTONIC
>+# define CLOCK_MONOTONIC 6
>+# endif
>+# ifndef HAVE_CLOCK_GETTIME
>+int clock_gettime(clockid_t clock_id, struct timespec *tp);
>+# endif
>+# ifndef HAVE_CLOCK_NANOSLEEP
>+int clock_nanosleep(clockid_t clock_id, int flags,
>+ const struct timespec *rqtp, struct timespec *rmtp);
>+# endif
> #endif
>
> #ifdef __cplusplus
>--
>2.21.1 (Apple Git-122.3)
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel
--
Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20200227/2ac14fed/attachment.html>
More information about the vlc-devel
mailing list