From f22c980173cf825bb41606fa897b462b08a7e6d9 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 28 Jul 2025 10:53:32 +0000 Subject: [PATCH 1/3] meson: add 'threads' dependency for pthread_* function checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the correct detection of these functions on some platforms like Alma Linux 8. Co-authored-by: Aydın Mercan --- meson.build | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/meson.build b/meson.build index c6859dec47..a920320a06 100644 --- a/meson.build +++ b/meson.build @@ -453,16 +453,6 @@ foreach fn, header : { 'flockfile': '#include ', 'getc_unlocked': '#include ', - # Thread control - 'pthread_attr_getstacksize': '#include ', - 'pthread_attr_setstacksize': '#include ', - 'pthread_barrier_init': '#include ', - 'pthread_set_name_np': '#include ', - 'pthread_setname_np': '#include ', - 'pthread_spin_init': '#include ', - 'pthread_yield': '#include ', - 'pthread_yield_np': '#include ', - # Processor control 'cpuset_getaffinity': '#include ', 'sched_getaffinity': '#include ', @@ -524,9 +514,31 @@ endif ### null_dep = dependency('', required: false) -thread_dep = dependency('threads') m_dep = cc.find_library('m', required: false) +## Threads +thread_dep = dependency('threads') + +foreach fn : [ + 'pthread_attr_getstacksize', + 'pthread_attr_setstacksize', + 'pthread_barrier_init', + 'pthread_set_name_np', + 'pthread_setname_np', + 'pthread_spin_init', + 'pthread_yield', + 'pthread_yield_np', +] + if cc.has_function( + fn, + prefix: '#include ', + args: sys_defines, + dependencies: thread_dep, + ) + config.set('HAVE_@0@'.format(fn.to_upper()), 1) + endif +endforeach + ## OpenSSL openssl_dep = [ dependency('libcrypto', version: '>=1.1.1'), From 96dad96ae5bc82a99c63c67463872782d0882e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 4 Aug 2025 17:03:42 +0200 Subject: [PATCH 2/3] Add support for setting thread stack size When running the isc_quota unit test with less than usual amount of RAM (e.g. in a CI for architectures with 32 bits of address space), the pthread_create() function fails with the "Resource temporarily unavailable (11):" error code. Add functions to get and set the thread stack size (if requested), and use these to set the thread stack size to smaller value in the isc_quota unit test. --- lib/isc/include/isc/thread.h | 5 ++++ lib/isc/os.c | 10 +++++++- lib/isc/thread.c | 49 ++++++++++++++++++------------------ lib/isc/thread_p.h | 6 +++++ tests/isc/mem_test.c | 3 +++ tests/isc/mutex_test.c | 4 +++ tests/isc/quota_test.c | 5 +++- tests/isc/rwlock_test.c | 4 +++ tests/isc/spinlock_test.c | 4 +++ 9 files changed, 63 insertions(+), 27 deletions(-) diff --git a/lib/isc/include/isc/thread.h b/lib/isc/include/isc/thread.h index 17c0fff9b1..1a9b0917f0 100644 --- a/lib/isc/include/isc/thread.h +++ b/lib/isc/include/isc/thread.h @@ -52,3 +52,8 @@ void isc_thread_setname(isc_thread_t thread, const char *name); #define isc_thread_self (uintptr_t)pthread_self + +size_t +isc_thread_getstacksize(void); +void +isc_thread_setstacksize(size_t stacksize); diff --git a/lib/isc/os.c b/lib/isc/os.c index b50248d591..8c3ced67c4 100644 --- a/lib/isc/os.c +++ b/lib/isc/os.c @@ -20,6 +20,7 @@ #include #include "os_p.h" +#include "thread_p.h" static unsigned int isc__os_ncpus = 0; static unsigned long isc__os_cacheline = ISC_OS_CACHELINE_SIZE; @@ -201,9 +202,16 @@ isc__os_initialize(void) { isc__os_cacheline = s; } #endif + + pthread_attr_init(&isc__thread_attr); + + size_t stacksize = isc_thread_getstacksize(); + if (stacksize != 0 && stacksize < THREAD_MINSTACKSIZE) { + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + } } void isc__os_shutdown(void) { - /* empty, but defined for completeness */; + pthread_attr_destroy(&isc__thread_attr); } diff --git a/lib/isc/thread.c b/lib/isc/thread.c index 5841a467fe..ea9e1fb028 100644 --- a/lib/isc/thread.c +++ b/lib/isc/thread.c @@ -40,12 +40,10 @@ #include "thread_p.h" -#ifndef THREAD_MINSTACKSIZE -#define THREAD_MINSTACKSIZE (1024U * 1024) -#endif /* ifndef THREAD_MINSTACKSIZE */ - static struct call_rcu_data *isc__thread_call_rcu_data = NULL; +pthread_attr_t isc__thread_attr; + /* * We can't use isc_mem API here, because it's called too early and the * memory debugging flags can be changed later causing mismatch between flags @@ -126,28 +124,9 @@ isc_thread_main(isc_threadfunc_t func, void *arg) { void isc_thread_create(isc_threadfunc_t func, void *arg, isc_thread_t *thread) { - int ret; - pthread_attr_t attr; - - pthread_attr_init(&attr); - -#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ - defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) - size_t stacksize; - ret = pthread_attr_getstacksize(&attr, &stacksize); - PTHREADS_RUNTIME_CHECK(pthread_attr_getstacksize, ret); - - if (stacksize < THREAD_MINSTACKSIZE) { - ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE); - PTHREADS_RUNTIME_CHECK(pthread_attr_setstacksize, ret); - } -#endif /* if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ - * defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) */ - - ret = pthread_create(thread, &attr, thread_run, thread_wrap(func, arg)); + int ret = pthread_create(thread, &isc__thread_attr, thread_run, + thread_wrap(func, arg)); PTHREADS_RUNTIME_CHECK(pthread_create, ret); - - pthread_attr_destroy(&attr); } void @@ -188,6 +167,26 @@ isc_thread_yield(void) { #endif /* if defined(HAVE_SCHED_YIELD) */ } +size_t +isc_thread_getstacksize(void) { + size_t stacksize = 0; + +#if HAVE_PTHREAD_ATTR_GETSTACKSIZE + int ret = pthread_attr_getstacksize(&isc__thread_attr, &stacksize); + PTHREADS_RUNTIME_CHECK(pthread_attr_getstacksize, ret); +#endif /* HAVE_PTHREAD_ATTR_GETSTACKSIZE */ + + return stacksize; +} + +void +isc_thread_setstacksize(size_t stacksize ISC_ATTR_UNUSED) { +#if HAVE_PTHREAD_ATTR_SETSTACKSIZE + int ret = pthread_attr_setstacksize(&isc__thread_attr, stacksize); + PTHREADS_RUNTIME_CHECK(pthread_attr_setstacksize, ret); +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ +} + void isc__thread_initialize(void) { isc__thread_call_rcu_data = create_call_rcu_data(0, -1); diff --git a/lib/isc/thread_p.h b/lib/isc/thread_p.h index 6ed32cd984..0fd02a9684 100644 --- a/lib/isc/thread_p.h +++ b/lib/isc/thread_p.h @@ -17,6 +17,12 @@ /*! \file */ +#ifndef THREAD_MINSTACKSIZE +#define THREAD_MINSTACKSIZE (1U * 1024 * 1024) +#endif /* ifndef THREAD_MINSTACKSIZE */ + +extern pthread_attr_t isc__thread_attr; + void isc__thread_initialize(void); diff --git a/tests/isc/mem_test.c b/tests/isc/mem_test.c index a19a8ee964..7cb7e06a8d 100644 --- a/tests/isc/mem_test.c +++ b/tests/isc/mem_test.c @@ -37,6 +37,7 @@ #include #include "mem_p.h" +#include "thread_p.h" #include @@ -516,6 +517,8 @@ ISC_RUN_TEST_IMPL(isc_mem_benchmark) { isc_time_t ts1, ts2; double t; + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + atomic_init(&mem_size, ITEM_SIZE); ts1 = isc_time_now(); diff --git a/tests/isc/mutex_test.c b/tests/isc/mutex_test.c index eb09ce0443..44c4b0ef29 100644 --- a/tests/isc/mutex_test.c +++ b/tests/isc/mutex_test.c @@ -36,6 +36,8 @@ #include #include +#include "thread_p.h" + #include static unsigned int loops = 100; @@ -124,6 +126,8 @@ ISC_RUN_TEST_IMPL(isc_mutex_benchmark) { size_t cont; int r; + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + memset(threads, 0, sizeof(*threads) * workers); expected_counter = ITERS * workers * loops * diff --git a/tests/isc/quota_test.c b/tests/isc/quota_test.c index 6b9677978d..dbc28015e4 100644 --- a/tests/isc/quota_test.c +++ b/tests/isc/quota_test.c @@ -32,6 +32,8 @@ #include #include +#include "thread_p.h" + #include isc_quota_t quota; @@ -268,9 +270,10 @@ quota_thread(void *qtip) { } ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { - UNUSED(state); int i; + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + isc_quota_init("a, 100); static qthreadinfo_t qtis[10]; isc_thread_t threads[10]; diff --git a/tests/isc/rwlock_test.c b/tests/isc/rwlock_test.c index efc9827c2f..a26334c92a 100644 --- a/tests/isc/rwlock_test.c +++ b/tests/isc/rwlock_test.c @@ -37,6 +37,8 @@ #include #include +#include "thread_p.h" + #include static unsigned int loops = 100; @@ -255,6 +257,8 @@ isc__rwlock_benchmark(isc_thread_t *threads, unsigned int nthreads, int dc; size_t cont; + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + expected_counter = ITERS * nthreads * loops * ((CNT_MAX - CNT_MIN) / DC + 1); diff --git a/tests/isc/spinlock_test.c b/tests/isc/spinlock_test.c index 6c739a713d..bd9fc37d0d 100644 --- a/tests/isc/spinlock_test.c +++ b/tests/isc/spinlock_test.c @@ -42,6 +42,8 @@ #include #include +#include "thread_p.h" + #include static unsigned int loops = 100; @@ -133,6 +135,8 @@ ISC_RUN_TEST_IMPL(isc_spinlock_benchmark) { int dc; size_t cont; + isc_thread_setstacksize(THREAD_MINSTACKSIZE); + memset(threads, 0, sizeof(*threads) * workers); expected_counter = ITERS * workers * loops * From f23bdc29ef6d46741a43a683b2434bcc32a12ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 5 Aug 2025 07:34:15 +0200 Subject: [PATCH 3/3] Document the current default stack sizes on different systems The default stack sizes varies between operating systems and between different system libc libraries from 128kB (Alpine Linux with MUSL) to 8M (Linux with glibc). Document the different values used to justify the value of THREAD_MINSTACKSIZE (currently set to 1MB). --- lib/isc/thread_p.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/isc/thread_p.h b/lib/isc/thread_p.h index 0fd02a9684..b31e6c3038 100644 --- a/lib/isc/thread_p.h +++ b/lib/isc/thread_p.h @@ -17,6 +17,14 @@ /*! \file */ +/* + * The current default stack sizes are as follows: + * - Linux glibc: 8MB + * - Linux musl: 128kB + * - FreeBSD: 2MB + * - OpenBSD: 512kB + * - NetBSD: 4MB + */ #ifndef THREAD_MINSTACKSIZE #define THREAD_MINSTACKSIZE (1U * 1024 * 1024) #endif /* ifndef THREAD_MINSTACKSIZE */