2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

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.
This commit is contained in:
Ondřej Surý 2025-08-04 17:03:42 +02:00
parent f22c980173
commit 96dad96ae5
No known key found for this signature in database
GPG Key ID: 2820F37E873DEA41
9 changed files with 63 additions and 27 deletions

View File

@ -52,3 +52,8 @@ void
isc_thread_setname(isc_thread_t thread, const char *name); isc_thread_setname(isc_thread_t thread, const char *name);
#define isc_thread_self (uintptr_t)pthread_self #define isc_thread_self (uintptr_t)pthread_self
size_t
isc_thread_getstacksize(void);
void
isc_thread_setstacksize(size_t stacksize);

View File

@ -20,6 +20,7 @@
#include <isc/uv.h> #include <isc/uv.h>
#include "os_p.h" #include "os_p.h"
#include "thread_p.h"
static unsigned int isc__os_ncpus = 0; static unsigned int isc__os_ncpus = 0;
static unsigned long isc__os_cacheline = ISC_OS_CACHELINE_SIZE; static unsigned long isc__os_cacheline = ISC_OS_CACHELINE_SIZE;
@ -201,9 +202,16 @@ isc__os_initialize(void) {
isc__os_cacheline = s; isc__os_cacheline = s;
} }
#endif #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 void
isc__os_shutdown(void) { isc__os_shutdown(void) {
/* empty, but defined for completeness */; pthread_attr_destroy(&isc__thread_attr);
} }

View File

@ -40,12 +40,10 @@
#include "thread_p.h" #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; 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 * 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 * 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 void
isc_thread_create(isc_threadfunc_t func, void *arg, isc_thread_t *thread) { isc_thread_create(isc_threadfunc_t func, void *arg, isc_thread_t *thread) {
int ret; int ret = pthread_create(thread, &isc__thread_attr, thread_run,
pthread_attr_t attr; thread_wrap(func, arg));
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));
PTHREADS_RUNTIME_CHECK(pthread_create, ret); PTHREADS_RUNTIME_CHECK(pthread_create, ret);
pthread_attr_destroy(&attr);
} }
void void
@ -188,6 +167,26 @@ isc_thread_yield(void) {
#endif /* if defined(HAVE_SCHED_YIELD) */ #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 void
isc__thread_initialize(void) { isc__thread_initialize(void) {
isc__thread_call_rcu_data = create_call_rcu_data(0, -1); isc__thread_call_rcu_data = create_call_rcu_data(0, -1);

View File

@ -17,6 +17,12 @@
/*! \file */ /*! \file */
#ifndef THREAD_MINSTACKSIZE
#define THREAD_MINSTACKSIZE (1U * 1024 * 1024)
#endif /* ifndef THREAD_MINSTACKSIZE */
extern pthread_attr_t isc__thread_attr;
void void
isc__thread_initialize(void); isc__thread_initialize(void);

View File

@ -37,6 +37,7 @@
#include <isc/util.h> #include <isc/util.h>
#include "mem_p.h" #include "mem_p.h"
#include "thread_p.h"
#include <tests/isc.h> #include <tests/isc.h>
@ -516,6 +517,8 @@ ISC_RUN_TEST_IMPL(isc_mem_benchmark) {
isc_time_t ts1, ts2; isc_time_t ts1, ts2;
double t; double t;
isc_thread_setstacksize(THREAD_MINSTACKSIZE);
atomic_init(&mem_size, ITEM_SIZE); atomic_init(&mem_size, ITEM_SIZE);
ts1 = isc_time_now(); ts1 = isc_time_now();

View File

@ -36,6 +36,8 @@
#include <isc/time.h> #include <isc/time.h>
#include <isc/util.h> #include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h> #include <tests/isc.h>
static unsigned int loops = 100; static unsigned int loops = 100;
@ -124,6 +126,8 @@ ISC_RUN_TEST_IMPL(isc_mutex_benchmark) {
size_t cont; size_t cont;
int r; int r;
isc_thread_setstacksize(THREAD_MINSTACKSIZE);
memset(threads, 0, sizeof(*threads) * workers); memset(threads, 0, sizeof(*threads) * workers);
expected_counter = ITERS * workers * loops * expected_counter = ITERS * workers * loops *

View File

@ -32,6 +32,8 @@
#include <isc/util.h> #include <isc/util.h>
#include <isc/uv.h> #include <isc/uv.h>
#include "thread_p.h"
#include <tests/isc.h> #include <tests/isc.h>
isc_quota_t quota; isc_quota_t quota;
@ -268,9 +270,10 @@ quota_thread(void *qtip) {
} }
ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { ISC_RUN_TEST_IMPL(isc_quota_callback_mt) {
UNUSED(state);
int i; int i;
isc_thread_setstacksize(THREAD_MINSTACKSIZE);
isc_quota_init(&quota, 100); isc_quota_init(&quota, 100);
static qthreadinfo_t qtis[10]; static qthreadinfo_t qtis[10];
isc_thread_t threads[10]; isc_thread_t threads[10];

View File

@ -37,6 +37,8 @@
#include <isc/time.h> #include <isc/time.h>
#include <isc/util.h> #include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h> #include <tests/isc.h>
static unsigned int loops = 100; static unsigned int loops = 100;
@ -255,6 +257,8 @@ isc__rwlock_benchmark(isc_thread_t *threads, unsigned int nthreads,
int dc; int dc;
size_t cont; size_t cont;
isc_thread_setstacksize(THREAD_MINSTACKSIZE);
expected_counter = ITERS * nthreads * loops * expected_counter = ITERS * nthreads * loops *
((CNT_MAX - CNT_MIN) / DC + 1); ((CNT_MAX - CNT_MIN) / DC + 1);

View File

@ -42,6 +42,8 @@
#include <isc/time.h> #include <isc/time.h>
#include <isc/util.h> #include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h> #include <tests/isc.h>
static unsigned int loops = 100; static unsigned int loops = 100;
@ -133,6 +135,8 @@ ISC_RUN_TEST_IMPL(isc_spinlock_benchmark) {
int dc; int dc;
size_t cont; size_t cont;
isc_thread_setstacksize(THREAD_MINSTACKSIZE);
memset(threads, 0, sizeof(*threads) * workers); memset(threads, 0, sizeof(*threads) * workers);
expected_counter = ITERS * workers * loops * expected_counter = ITERS * workers * loops *