From: Ondřej Surý Date: Mon, 4 Aug 2025 15:03:42 +0000 (+0200) Subject: Add support for setting thread stack size X-Git-Tag: v9.21.11~7^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96dad96ae5bc82a99c63c67463872782d0882e52;p=thirdparty%2Fbind9.git 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. --- diff --git a/lib/isc/include/isc/thread.h b/lib/isc/include/isc/thread.h index 17c0fff9b18..1a9b0917f03 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 b50248d5919..8c3ced67c4b 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 5841a467fea..ea9e1fb028a 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 6ed32cd984c..0fd02a9684a 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 a19a8ee9649..7cb7e06a8d3 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 eb09ce04433..44c4b0ef295 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 6b9677978df..dbc28015e4f 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 efc9827c2fa..a26334c92aa 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 6c739a713d9..bd9fc37d0d1 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 *