Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/lib/libtpool/tests/libtpool_test.c
39488 views
1
#include <sys/stdtypes.h>
2
#include <sys/sysctl.h>
3
#include <errno.h>
4
#include <pthread.h>
5
6
#include <thread_pool.h>
7
8
#include <atf-c.h>
9
10
static void
11
tp_delay(void *arg)
12
{
13
pthread_barrier_t *barrier = arg;
14
int r;
15
16
/* Block this task until all thread pool workers have been created. */
17
r = pthread_barrier_wait(barrier);
18
ATF_REQUIRE_MSG(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD,
19
"pthread_barrier_wait failed: %s", strerror(r));
20
}
21
22
/*
23
* NB: we could reduce the test's resource cost by using rctl(4). But that
24
* isn't enabled by default. And even with a thread limit of 1500, it takes <
25
* 0.1s to run on my machine. So I don't think it's worth optimizing for the
26
* case where rctl is available.
27
*/
28
ATF_TC(complete_exhaustion);
29
ATF_TC_HEAD(complete_exhaustion, tc)
30
{
31
atf_tc_set_md_var(tc, "descr",
32
"A thread pool should fail to schedule tasks if it is completely impossible to spawn any threads.");
33
}
34
35
ATF_TC_BODY(complete_exhaustion, tc)
36
{
37
pthread_barrier_t barrier;
38
tpool_t *tp0, *tp1;
39
size_t len;
40
int max_threads_per_proc = 0;
41
int nworkers;
42
int r, i;
43
44
len = sizeof(max_threads_per_proc);
45
r = sysctlbyname("kern.threads.max_threads_per_proc",
46
&max_threads_per_proc, &len, NULL, 0);
47
ATF_REQUIRE_EQ_MSG(r, 0, "sysctlbyname: %s", strerror(errno));
48
nworkers = max_threads_per_proc - 1;
49
pthread_barrier_init(&barrier, NULL, max_threads_per_proc);
50
51
/*
52
* Create the first thread pool and spawn the maximum allowed number of
53
* processes.
54
*/
55
tp0 = tpool_create(nworkers, nworkers, 1, NULL);
56
ATF_REQUIRE(tp0 != NULL);
57
for (i = 0; i < nworkers; i++) {
58
ATF_REQUIRE_EQ(tpool_dispatch(tp0, tp_delay, &barrier), 0);
59
}
60
61
/*
62
* Now create a second thread pool. Unable to create new threads, the
63
* dispatch function should return an error.
64
*/
65
tp1 = tpool_create(nworkers, 2 * nworkers, 1, NULL);
66
ATF_REQUIRE(tp1 != NULL);
67
ATF_REQUIRE_EQ(tpool_dispatch(tp1, tp_delay, NULL), -1);
68
69
/* Cleanup */
70
r = pthread_barrier_wait(&barrier);
71
ATF_REQUIRE_MSG(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD,
72
"pthread_barrier_wait failed: %s", strerror(r));
73
tpool_wait(tp1);
74
tpool_wait(tp0);
75
}
76
77
ATF_TP_ADD_TCS(tp)
78
{
79
ATF_TP_ADD_TC(tp, complete_exhaustion);
80
81
return (atf_no_error());
82
}
83
84