2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 21:47:59 +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
commit f635bf4df8
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);
#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 "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);
}

View File

@ -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);

View File

@ -17,6 +17,20 @@
/*! \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
isc__thread_initialize(void);

View File

@ -453,16 +453,6 @@ foreach fn, header : {
'flockfile': '#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
'cpuset_getaffinity': '#include <sys/cpuset.h>',
'sched_getaffinity': '#include <sched.h>',
@ -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 <pthread.h>',
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'),

View File

@ -37,6 +37,7 @@
#include <isc/util.h>
#include "mem_p.h"
#include "thread_p.h"
#include <tests/isc.h>
@ -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();

View File

@ -36,6 +36,8 @@
#include <isc/time.h>
#include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h>
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 *

View File

@ -32,6 +32,8 @@
#include <isc/util.h>
#include <isc/uv.h>
#include "thread_p.h"
#include <tests/isc.h>
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(&quota, 100);
static qthreadinfo_t qtis[10];
isc_thread_t threads[10];

View File

@ -37,6 +37,8 @@
#include <isc/time.h>
#include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h>
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);

View File

@ -42,6 +42,8 @@
#include <isc/time.h>
#include <isc/util.h>
#include "thread_p.h"
#include <tests/isc.h>
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 *