From edc735de775a24ce09ce9474271a71188aeabfac Mon Sep 17 00:00:00 2001 From: Marlene JACQUIER Date: Fri, 19 Jan 2024 14:11:14 +0000 Subject: gstreamer1.0: use futex_time64 syscall if available (32-bit systems) Patch backported from 1.20.5 --- ...-Use-futex_time64-syscall-if-available-32.patch | 211 +++++++++++++++++++++ .../gstreamer/gstreamer1.0_1.20.3.imx.bb | 1 + 2 files changed, 212 insertions(+) create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0006-systemclock-Use-futex_time64-syscall-if-available-32.patch diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0006-systemclock-Use-futex_time64-syscall-if-available-32.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0006-systemclock-Use-futex_time64-syscall-if-available-32.patch new file mode 100644 index 00000000..f3e7975c --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0006-systemclock-Use-futex_time64-syscall-if-available-32.patch @@ -0,0 +1,211 @@ +From 9ca6b1196e31a4a483fdddad191221616e2c9c3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Mon, 12 Dec 2022 11:34:51 +0200 +Subject: [PATCH] systemclock: Use `futex_time64` syscall if available (32-bit + systems) and use correct `struct timespec` definition + +See also https://gitlab.gnome.org/GNOME/glib/-/issues/2634 + +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1648 + +Part-of: +--- + gst/gstsystemclock.c | 125 ++++++++++++++++++--- + meson.build | 11 +- + 2 files changed, 121 insertions(+), 15 deletions(-) + +diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c +index 6d0b6ec47b..7d8efb171e 100644 +--- a/gst/gstsystemclock.c ++++ b/gst/gstsystemclock.c +@@ -70,11 +70,15 @@ + #define GST_SYSTEM_CLOCK_WAIT(clock) g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_SYSTEM_CLOCK_GET_LOCK(clock)) + #define GST_SYSTEM_CLOCK_BROADCAST(clock) g_cond_broadcast(GST_SYSTEM_CLOCK_GET_COND(clock)) + +-#if defined(HAVE_FUTEX) ++#if defined(HAVE_FUTEX) || defined(HAVE_FUTEX_TIME64) + #include + #include + #include + ++#if !defined(__NR_futex) && !defined(__NR_futex_time64) ++#error "Neither __NR_futex nor __NR_futex_time64 are defined but were found by meson" ++#endif ++ + #ifndef FUTEX_WAIT_BITSET_PRIVATE + #define FUTEX_WAIT_BITSET_PRIVATE FUTEX_WAIT_BITSET + #endif +@@ -123,14 +127,35 @@ gst_futex_cond_broadcast (guint * cond_val) + { + g_atomic_int_inc (cond_val); + ++#if defined(__NR_futex_time64) ++ { ++ int res; ++ res = syscall (__NR_futex_time64, cond_val, (gsize) FUTEX_WAKE_PRIVATE, ++ (gsize) INT_MAX, NULL); ++ ++ /* If the syscall does not exist (`ENOSYS`), we retry again below with the ++ * normal `futex` syscall. This can happen if newer kernel headers are ++ * used than the kernel that is actually running. ++ */ ++#ifdef __NR_futex ++ if (res >= 0 || errno != ENOSYS) { ++#else ++ { ++#endif ++ return; ++ } ++ } ++#endif ++ ++#if defined(__NR_futex) + syscall (__NR_futex, cond_val, (gsize) FUTEX_WAKE_PRIVATE, (gsize) INT_MAX, + NULL); ++#endif + } + + static gboolean + gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time) + { +- struct timespec end; + guint sampled; + int res; + gboolean success; +@@ -138,20 +163,92 @@ gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time) + if (end_time < 0) + return FALSE; + +- end.tv_sec = end_time / 1000000000; +- end.tv_nsec = end_time % 1000000000; +- + sampled = *cond_val; + g_mutex_unlock (mutex); +- /* 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, +- (gsize) sampled, &end, NULL, FUTEX_BITSET_MATCH_ANY); +- success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE; +- g_mutex_lock (mutex); +- +- return success; ++ ++ /* `struct timespec` as defined by the libc headers does not necessarily ++ * have any relation to the one used by the kernel for the `futex` syscall. ++ * ++ * Specifically, the libc headers might use 64-bit `time_t` while the kernel ++ * headers use 32-bit `__kernel_old_time_t` on certain systems. ++ * ++ * To get around this problem we ++ * a) check if `futex_time64` is available, which only exists on 32-bit ++ * platforms and always uses 64-bit `time_t`. ++ * b) otherwise (or if that returns `ENOSYS`), we call the normal `futex` ++ * syscall with the `struct timespec_t` used by the kernel, which uses ++ * `__kernel_long_t` for both its fields. We use that instead of ++ * `__kernel_old_time_t` because it is equivalent and available in the ++ * kernel headers for a longer time. ++ * ++ * Also some 32-bit systems do not define `__NR_futex` at all and only ++ * define `__NR_futex_time64`. ++ */ ++ ++#ifdef __NR_futex_time64 ++ { ++ struct ++ { ++ gint64 tv_sec; ++ gint64 tv_nsec; ++ } end; ++ ++ end.tv_sec = end_time / 1000000000; ++ end.tv_nsec = end_time % 1000000000; ++ ++ /* we use FUTEX_WAIT_BITSET_PRIVATE rather than FUTEX_WAIT_PRIVATE to be ++ * able to use absolute time */ ++ res = ++ syscall (__NR_futex_time64, cond_val, (gsize) FUTEX_WAIT_BITSET_PRIVATE, ++ (gsize) sampled, &end, NULL, FUTEX_BITSET_MATCH_ANY); ++ ++ /* If the syscall does not exist (`ENOSYS`), we retry again below with the ++ * normal `futex` syscall. This can happen if newer kernel headers are ++ * used than the kernel that is actually running. ++ */ ++#ifdef __NR_futex ++ if (res >= 0 || errno != ENOSYS) { ++#else ++ { ++#endif ++ success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE; ++ g_mutex_lock (mutex); ++ ++ return success; ++ } ++ } ++#endif ++ ++#ifdef __NR_futex ++ { ++ struct ++ { ++ __kernel_long_t tv_sec; ++ __kernel_long_t tv_nsec; ++ } end; ++ ++ /* Make sure to only ever call this if the end time actually fits into the ++ * target type */ ++ g_assert (sizeof (__kernel_long_t) >= 8 ++ || end_time / 1000000000 <= G_MAXINT32); ++ ++ end.tv_sec = end_time / 1000000000; ++ end.tv_nsec = end_time % 1000000000; ++ ++ /* 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, ++ (gsize) sampled, &end, NULL, FUTEX_BITSET_MATCH_ANY); ++ success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE; ++ g_mutex_lock (mutex); ++ ++ return success; ++ } ++#endif ++ ++ /* We can't end up here because of the checks above */ ++ g_assert_not_reached (); + } + + #elif defined (G_OS_UNIX) +diff --git a/meson.build b/meson.build +index 0641f7678b..7331c66150 100644 +--- a/meson.build ++++ b/meson.build +@@ -294,7 +294,7 @@ if cc.has_header_symbol('pthread.h', 'pthread_cond_timedwait_relative_np') + endif + + # Check for futex(2) +-if cc.links('''#include ++if cc.compiles('''#include + #include + #include + int main (int argc, char ** argv) { +@@ -303,6 +303,15 @@ if cc.links('''#include + }''', name : 'futex(2) system call') + cdata.set('HAVE_FUTEX', 1) + endif ++if cc.compiles('''#include ++ #include ++ #include ++ int main (int argc, char ** argv) { ++ syscall (__NR_futex_time64, NULL, FUTEX_WAKE, FUTEX_WAIT); ++ return 0; ++ }''', name : 'futex(2) system call') ++ cdata.set('HAVE_FUTEX_TIME64', 1) ++endif + + # Check for posix timers and monotonic clock + time_prefix = '#include \n' +-- +2.25.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0_1.20.3.imx.bb b/recipes-multimedia/gstreamer/gstreamer1.0_1.20.3.imx.bb index 2c419601..850a5385 100644 --- a/recipes-multimedia/gstreamer/gstreamer1.0_1.20.3.imx.bb +++ b/recipes-multimedia/gstreamer/gstreamer1.0_1.20.3.imx.bb @@ -29,6 +29,7 @@ SRC_URI = "https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-${PV}.tar.x file://0003-tests-use-a-dictionaries-for-environment.patch;striplevel=3 \ file://0004-tests-add-helper-script-to-run-the-installed_tests.patch;striplevel=3 \ file://0005-tests-remove-gstbin-test_watch_for_state_change-test.patch \ + file://0006-systemclock-Use-futex_time64-syscall-if-available-32.patch \ " SRC_URI[sha256sum] = "de094a404a3ad8f4977829ea87edf695a4da0b5c8f613ebe54ab414bac89f031" -- cgit v1.2.3-54-g00ecf