summaryrefslogtreecommitdiff
path: root/user/gstreamer/time64.patch
blob: 89c88c38097c228948908797ebad6b589e2ee438 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
From 664fc63a246cba97e202f712aa48105f46a9ff69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Mon, 12 Dec 2022 11:34:51 +0200
Subject: [PATCH] systemclock: Use `futex_time64` syscall on x32 and other
 platforms that always use a 32-bit `struct timespec` for the normal `futex`
 syscall

See also https://gitlab.gnome.org/GNOME/glib/-/issues/2634
---
 gst/gstsystemclock.c | 26 +++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c
index 6d0b6ec47b6..8c396d2c7b4 100644
--- a/gst/gstsystemclock.c
+++ b/gst/gstsystemclock.c
@@ -130,7 +130,31 @@ gst_futex_cond_broadcast (guint * cond_val)
 static gboolean
 gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time)
 {
+  /* On x32 (ILP32 ABI on x86_64) and potentially sparc64, the raw futex()
+   * syscall takes a 32-bit timespan argument *regardless* of whether userspace
+   * is using 32-bit or 64-bit `struct timespec`. This means that we can’t
+   * unconditionally pass a `struct timespec` pointer into the syscall.
+   *
+   * Assume that any such platform is new enough to define the
+   * `__NR_futex_time64` workaround syscall (which accepts 64-bit timespecs,
+   * introduced in kernel 5.1), and use that to pass a 64-bit timespec instead.
+   *
+   * `clock_gettime()` on such systems will either return a 32-bit `struct
+   * timespec`, in which case the values we will get passed in here are
+   * already not y2038-safe, or `struct timespec` is using 64-bit `time_t` and
+   * everything is fine.
+   */
+#ifdef __NR_futex_time64
+  struct
+  {
+    gint64 tv_sec;
+    gint64 tv_nsec;
+  } end;
+  const long int futex_syscall_id = __NR_futex_time64;
+#else
   struct timespec end;
+  const long int futex_syscall_id = __NR_futex;
+#endif
   guint sampled;
   int res;
   gboolean success;
@@ -146,7 +170,7 @@ gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time)
   /* we use FUTEX_WAIT_BITSET_PRIVATE rather than FUTEX_WAIT_PRIVATE to be
    * able to use absolute time */
   res =
-      syscall (__NR_futex, cond_val, (gsize) FUTEX_WAIT_BITSET_PRIVATE,
+      syscall (futex_syscall_id, cond_val, (gsize) FUTEX_WAIT_BITSET_PRIVATE,
       (gsize) sampled, &end, NULL, FUTEX_BITSET_MATCH_ANY);
   success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE;
   g_mutex_lock (mutex);
-- 
GitLab