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)