2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 15:45:25 +00:00

fix: test: Add support for small stack size for threads

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.

Merge branch 'aram/isc-thread-stack-size-small' into 'main'

See merge request isc-projects/bind9!10778
This commit is contained in:
Ondřej Surý
2025-08-05 11:24:35 +02:00
10 changed files with 94 additions and 38 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,20 @@
/*! \file */ /*! \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 */
extern pthread_attr_t isc__thread_attr;
void void
isc__thread_initialize(void); isc__thread_initialize(void);

View File

@@ -453,16 +453,6 @@ foreach fn, header : {
'flockfile': '#include <stdio.h>', 'flockfile': '#include <stdio.h>',
'getc_unlocked': '#include <stdio.h>', 'getc_unlocked': '#include <stdio.h>',
# Thread control
'pthread_attr_getstacksize': '#include <pthread.h>',
'pthread_attr_setstacksize': '#include <pthread.h>',
'pthread_barrier_init': '#include <pthread.h>',
'pthread_set_name_np': '#include <pthread.h>',
'pthread_setname_np': '#include <pthread.h>',
'pthread_spin_init': '#include <pthread.h>',
'pthread_yield': '#include <pthread.h>',
'pthread_yield_np': '#include <pthread.h>',
# Processor control # Processor control
'cpuset_getaffinity': '#include <sys/cpuset.h>', 'cpuset_getaffinity': '#include <sys/cpuset.h>',
'sched_getaffinity': '#include <sched.h>', 'sched_getaffinity': '#include <sched.h>',
@@ -524,9 +514,31 @@ endif
### ###
null_dep = dependency('', required: false) null_dep = dependency('', required: false)
thread_dep = dependency('threads')
m_dep = cc.find_library('m', required: false) 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 <pthread.h>',
args: sys_defines,
dependencies: thread_dep,
)
config.set('HAVE_@0@'.format(fn.to_upper()), 1)
endif
endforeach
## OpenSSL ## OpenSSL
openssl_dep = [ openssl_dep = [
dependency('libcrypto', version: '>=1.1.1'), dependency('libcrypto', version: '>=1.1.1'),

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 *