shithub: dav1d

Download patch

ref: 6b611d36acab8ce1afdd528599322bb6b2d28727
parent: eb211838b478491ac17ea2cbfa6e2797376e369e
author: Henrik Gramner <gramner@twoorioles.com>
date: Thu Dec 12 18:09:56 EST 2019

Linux: Add a workaround for a glibc stack size issue

--- a/meson.build
+++ b/meson.build
@@ -84,13 +84,15 @@
 
 optional_arguments = []
 
-# Define _POSIX_C_SOURCE to POSIX.1–2001 (IEEE Std 1003.1-2001)
-test_args += '-D_POSIX_C_SOURCE=200112L'
-add_project_arguments('-D_POSIX_C_SOURCE=200112L', language: 'c')
-
-if host_machine.system() == 'darwin'
+if host_machine.system() == 'linux'
+    test_args += '-D_GNU_SOURCE'
+    add_project_arguments('-D_GNU_SOURCE', language: 'c')
+elif host_machine.system() == 'darwin'
     test_args += '-D_DARWIN_C_SOURCE'
     add_project_arguments('-D_DARWIN_C_SOURCE', language: 'c')
+else
+    test_args += '-D_POSIX_C_SOURCE=200112L'
+    add_project_arguments('-D_POSIX_C_SOURCE=200112L', language: 'c')
 endif
 
 if host_machine.system() == 'windows'
@@ -130,6 +132,12 @@
         cdata.set('HAVE_CLOCK_GETTIME', 1)
     endif
 endif
+
+libdl_dependency = []
+if host_machine.system() == 'linux'
+    libdl_dependency = cc.find_library('dl', required : false)
+endif
+
 
 # Header checks
 
--- a/src/lib.c
+++ b/src/lib.c
@@ -31,6 +31,10 @@
 #include <errno.h>
 #include <string.h>
 
+#ifdef __linux__
+#include <dlfcn.h>
+#endif
+
 #include "dav1d/dav1d.h"
 #include "dav1d/data.h"
 
@@ -94,7 +98,19 @@
 
     pthread_attr_t thread_attr;
     if (pthread_attr_init(&thread_attr)) return DAV1D_ERR(ENOMEM);
-    pthread_attr_setstacksize(&thread_attr, 1024 * 1024);
+    size_t stack_size = 1024 * 1024;
+#ifdef __linux__
+    /* glibc has an issue where the size of the TLS is subtracted from the stack
+     * size instead of allocated separately. As a result the specified stack
+     * size may be insufficient when used in an application with large amounts
+     * of TLS data. The following is a workaround to compensate for that.
+     * See https://sourceware.org/bugzilla/show_bug.cgi?id=11787 */
+    size_t (*const get_minstack)(const pthread_attr_t*) =
+        dlsym(RTLD_DEFAULT, "__pthread_get_minstack");
+    if (get_minstack)
+        stack_size += get_minstack(&thread_attr) - PTHREAD_STACK_MIN;
+#endif
+    pthread_attr_setstacksize(&thread_attr, stack_size);
 
     Dav1dContext *const c = *c_out = dav1d_alloc_aligned(sizeof(*c), 32);
     if (!c) goto error;
--- a/src/meson.build
+++ b/src/meson.build
@@ -278,6 +278,7 @@
         stdatomic_dependency,
         thread_dependency,
         thread_compat_dep,
+        libdl_dependency,
         ],
     c_args : [stackalign_flag, api_export_flags],
     version : dav1d_soname_version,
--- a/src/thread.h
+++ b/src/thread.h
@@ -72,9 +72,10 @@
 }
 
 static inline int pthread_attr_setstacksize(pthread_attr_t *const attr,
-                                            const unsigned stack_size)
+                                            const size_t stack_size)
 {
-    attr->stack_size = stack_size;
+    if (stack_size > UINT_MAX) return 1;
+    attr->stack_size = (unsigned) stack_size;
     return 0;
 }
 
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -90,7 +90,12 @@
         include_directories: dav1d_inc_dirs,
         c_args: [stackalign_flag, stackrealign_flag],
         build_by_default: false,
-        dependencies : [thread_dependency, rt_dependency, m_lib],
+        dependencies : [
+            thread_dependency,
+            rt_dependency,
+            libdl_dependency,
+            m_lib,
+            ],
         )
 
     test('checkasm', checkasm, is_parallel: false)