diff options
| author | Alan Somers <asomers@FreeBSD.org> | 2024-05-07 17:48:33 +0000 |
|---|---|---|
| committer | Alan Somers <asomers@FreeBSD.org> | 2025-06-15 16:01:37 +0000 |
| commit | 5c1ba994a8bcb6676ea3d1bb21b072b90e2d3ae9 (patch) | |
| tree | a1ecc3f9d55aab1c74818d1b97cfcd78ab07a9ad /cddl/lib | |
| parent | ece617cda6b5999e6e57c2227f98c18c1ca1d79d (diff) | |
Diffstat (limited to 'cddl/lib')
| -rw-r--r-- | cddl/lib/libtpool/Makefile | 5 | ||||
| -rw-r--r-- | cddl/lib/libtpool/tests/Makefile | 12 | ||||
| -rw-r--r-- | cddl/lib/libtpool/tests/libtpool_test.c | 78 |
3 files changed, 95 insertions, 0 deletions
diff --git a/cddl/lib/libtpool/Makefile b/cddl/lib/libtpool/Makefile index 2afaf0c417e9..3ab625dd306b 100644 --- a/cddl/lib/libtpool/Makefile +++ b/cddl/lib/libtpool/Makefile @@ -22,4 +22,9 @@ CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccomp CFLAGS+= -DHAVE_ISSETUGID CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h +.include <src.opts.mk> + +HAS_TESTS= +SUBDIR.${MK_TESTS}+= tests + .include <bsd.lib.mk> diff --git a/cddl/lib/libtpool/tests/Makefile b/cddl/lib/libtpool/tests/Makefile new file mode 100644 index 000000000000..d87f5fc86789 --- /dev/null +++ b/cddl/lib/libtpool/tests/Makefile @@ -0,0 +1,12 @@ +ZFSTOP= ${SRCTOP}/sys/contrib/openzfs + +ATF_TESTS_C+= libtpool_test + +TEST_METADATA+= timeout="10" + +CFLAGS+= -I${ZFSTOP}/include \ + -I${ZFSTOP}/lib/libspl/include + +LIBADD+= pthread tpool + +.include <bsd.test.mk> diff --git a/cddl/lib/libtpool/tests/libtpool_test.c b/cddl/lib/libtpool/tests/libtpool_test.c new file mode 100644 index 000000000000..42726a13420c --- /dev/null +++ b/cddl/lib/libtpool/tests/libtpool_test.c @@ -0,0 +1,78 @@ +#include <sys/stdtypes.h> +#include <sys/sysctl.h> +#include <errno.h> +#include <pthread.h> + +#include <thread_pool.h> + +#include <atf-c.h> + +static void +tp_delay(void *arg) +{ + pthread_barrier_t *barrier = arg; + + /* Block this task until all thread pool workers have been created. */ + pthread_barrier_wait(barrier); +} + +/* + * NB: we could reduce the test's resource cost by using rctl(4). But that + * isn't enabled by default. And even with a thread limit of 1500, it takes < + * 0.1s to run on my machine. So I don't think it's worth optimizing for the + * case where rctl is available. + */ +ATF_TC(complete_exhaustion); +ATF_TC_HEAD(complete_exhaustion, tc) +{ + atf_tc_set_md_var(tc, "descr", + "A thread pool should fail to schedule tasks if it is completely impossible to spawn any threads."); +} + +ATF_TC_BODY(complete_exhaustion, tc) +{ + pthread_barrier_t barrier; + tpool_t *tp0, *tp1; + size_t len; + int max_threads_per_proc = 0; + int nworkers; + int r, i; + + + len = sizeof(max_threads_per_proc); + r = sysctlbyname("kern.threads.max_threads_per_proc", + &max_threads_per_proc, &len, NULL, 0); + ATF_REQUIRE_EQ_MSG(r, 0, "sysctlbyname: %s", strerror(errno)); + nworkers = max_threads_per_proc - 1; + pthread_barrier_init(&barrier, NULL, max_threads_per_proc); + + /* + * Create the first thread pool and spawn the maximum allowed number of + * processes. + */ + tp0 = tpool_create(nworkers, nworkers, 1, NULL); + ATF_REQUIRE(tp0 != NULL); + for (i = 0; i < nworkers; i++) { + ATF_REQUIRE_EQ(tpool_dispatch(tp0, tp_delay, &barrier), 0); + } + + /* + * Now create a second thread pool. Unable to create new threads, the + * dispatch function should return an error. + */ + tp1 = tpool_create(nworkers, 2 * nworkers, 1, NULL); + ATF_REQUIRE(tp1 != NULL); + ATF_REQUIRE_EQ(tpool_dispatch(tp1, tp_delay, NULL), -1); + + /* Cleanup */ + ATF_REQUIRE_EQ(pthread_barrier_wait(&barrier), 0); + tpool_wait(tp1); + tpool_wait(tp0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, complete_exhaustion); + + return (atf_no_error()); +} |
