xref: /freebsd/cddl/lib/libtpool/tests/libtpool_test.c (revision 7b26124ae106283952e1e61d07f0eecda5c361a0)
15c1ba994SAlan Somers #include <sys/stdtypes.h>
25c1ba994SAlan Somers #include <sys/sysctl.h>
35c1ba994SAlan Somers #include <errno.h>
45c1ba994SAlan Somers #include <pthread.h>
55c1ba994SAlan Somers 
65c1ba994SAlan Somers #include <thread_pool.h>
75c1ba994SAlan Somers 
85c1ba994SAlan Somers #include <atf-c.h>
95c1ba994SAlan Somers 
105c1ba994SAlan Somers static void
tp_delay(void * arg)115c1ba994SAlan Somers tp_delay(void *arg)
125c1ba994SAlan Somers {
135c1ba994SAlan Somers 	pthread_barrier_t *barrier = arg;
14*7b26124aSMark Johnston 	int r;
155c1ba994SAlan Somers 
165c1ba994SAlan Somers 	/* Block this task until all thread pool workers have been created. */
17*7b26124aSMark Johnston 	r = pthread_barrier_wait(barrier);
18*7b26124aSMark Johnston 	ATF_REQUIRE_MSG(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD,
19*7b26124aSMark Johnston 	    "pthread_barrier_wait failed: %s", strerror(r));
205c1ba994SAlan Somers }
215c1ba994SAlan Somers 
225c1ba994SAlan Somers /*
235c1ba994SAlan Somers  * NB: we could reduce the test's resource cost by using rctl(4).  But that
245c1ba994SAlan Somers  * isn't enabled by default.  And even with a thread limit of 1500, it takes <
255c1ba994SAlan Somers  * 0.1s to run on my machine.  So I don't think it's worth optimizing for the
265c1ba994SAlan Somers  * case where rctl is available.
275c1ba994SAlan Somers  */
285c1ba994SAlan Somers ATF_TC(complete_exhaustion);
ATF_TC_HEAD(complete_exhaustion,tc)295c1ba994SAlan Somers ATF_TC_HEAD(complete_exhaustion, tc)
305c1ba994SAlan Somers {
315c1ba994SAlan Somers 	atf_tc_set_md_var(tc, "descr",
325c1ba994SAlan Somers 	    "A thread pool should fail to schedule tasks if it is completely impossible to spawn any threads.");
335c1ba994SAlan Somers }
345c1ba994SAlan Somers 
ATF_TC_BODY(complete_exhaustion,tc)355c1ba994SAlan Somers ATF_TC_BODY(complete_exhaustion, tc)
365c1ba994SAlan Somers {
375c1ba994SAlan Somers 	pthread_barrier_t barrier;
385c1ba994SAlan Somers 	tpool_t *tp0, *tp1;
395c1ba994SAlan Somers 	size_t len;
405c1ba994SAlan Somers 	int max_threads_per_proc = 0;
415c1ba994SAlan Somers 	int nworkers;
425c1ba994SAlan Somers 	int r, i;
435c1ba994SAlan Somers 
445c1ba994SAlan Somers 	len = sizeof(max_threads_per_proc);
455c1ba994SAlan Somers 	r = sysctlbyname("kern.threads.max_threads_per_proc",
465c1ba994SAlan Somers 	    &max_threads_per_proc, &len, NULL, 0);
475c1ba994SAlan Somers 	ATF_REQUIRE_EQ_MSG(r, 0, "sysctlbyname: %s", strerror(errno));
485c1ba994SAlan Somers 	nworkers = max_threads_per_proc - 1;
495c1ba994SAlan Somers 	pthread_barrier_init(&barrier, NULL, max_threads_per_proc);
505c1ba994SAlan Somers 
515c1ba994SAlan Somers 	/*
525c1ba994SAlan Somers 	 * Create the first thread pool and spawn the maximum allowed number of
535c1ba994SAlan Somers 	 * processes.
545c1ba994SAlan Somers 	 */
555c1ba994SAlan Somers 	tp0 = tpool_create(nworkers, nworkers, 1, NULL);
565c1ba994SAlan Somers 	ATF_REQUIRE(tp0 != NULL);
575c1ba994SAlan Somers 	for (i = 0; i < nworkers; i++) {
585c1ba994SAlan Somers 		ATF_REQUIRE_EQ(tpool_dispatch(tp0, tp_delay, &barrier), 0);
595c1ba994SAlan Somers 	}
605c1ba994SAlan Somers 
615c1ba994SAlan Somers 	/*
625c1ba994SAlan Somers 	 * Now create a second thread pool.  Unable to create new threads, the
635c1ba994SAlan Somers 	 * dispatch function should return an error.
645c1ba994SAlan Somers 	 */
655c1ba994SAlan Somers 	tp1 = tpool_create(nworkers, 2 * nworkers, 1, NULL);
665c1ba994SAlan Somers 	ATF_REQUIRE(tp1 != NULL);
675c1ba994SAlan Somers 	ATF_REQUIRE_EQ(tpool_dispatch(tp1, tp_delay, NULL), -1);
685c1ba994SAlan Somers 
695c1ba994SAlan Somers 	/* Cleanup */
70*7b26124aSMark Johnston 	r = pthread_barrier_wait(&barrier);
71*7b26124aSMark Johnston 	ATF_REQUIRE_MSG(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD,
72*7b26124aSMark Johnston 	    "pthread_barrier_wait failed: %s", strerror(r));
735c1ba994SAlan Somers 	tpool_wait(tp1);
745c1ba994SAlan Somers 	tpool_wait(tp0);
755c1ba994SAlan Somers }
765c1ba994SAlan Somers 
ATF_TP_ADD_TCS(tp)775c1ba994SAlan Somers ATF_TP_ADD_TCS(tp)
785c1ba994SAlan Somers {
795c1ba994SAlan Somers 	ATF_TP_ADD_TC(tp, complete_exhaustion);
805c1ba994SAlan Somers 
815c1ba994SAlan Somers 	return (atf_no_error());
825c1ba994SAlan Somers }
83