Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/sys/cpuset_test.c
39530 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2020-2021 Kyle Evans <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/cpuset.h>
30
#include <sys/jail.h>
31
#include <sys/procdesc.h>
32
#include <sys/select.h>
33
#include <sys/socket.h>
34
#include <sys/uio.h>
35
#include <sys/wait.h>
36
37
#include <errno.h>
38
#include <stdio.h>
39
#include <unistd.h>
40
41
#include <atf-c.h>
42
43
#define SP_PARENT 0
44
#define SP_CHILD 1
45
46
struct jail_test_info {
47
cpuset_t jail_tidmask;
48
cpusetid_t jail_cpuset;
49
cpusetid_t jail_child_cpuset;
50
};
51
52
struct jail_test_cb_params {
53
struct jail_test_info info;
54
cpuset_t mask;
55
cpusetid_t rootid;
56
cpusetid_t setid;
57
};
58
59
typedef void (*jail_test_cb)(struct jail_test_cb_params *);
60
61
#define FAILURE_JAIL 42
62
#define FAILURE_MASK 43
63
#define FAILURE_JAILSET 44
64
#define FAILURE_PIDSET 45
65
#define FAILURE_SEND 46
66
#define FAILURE_DEADLK 47
67
#define FAILURE_ATTACH 48
68
#define FAILURE_BADAFFIN 49
69
#define FAILURE_SUCCESS 50
70
71
static const char *
72
do_jail_errstr(int error)
73
{
74
75
switch (error) {
76
case FAILURE_JAIL:
77
return ("jail_set(2) failed");
78
case FAILURE_MASK:
79
return ("Failed to get the thread cpuset mask");
80
case FAILURE_JAILSET:
81
return ("Failed to get the jail setid");
82
case FAILURE_PIDSET:
83
return ("Failed to get the pid setid");
84
case FAILURE_SEND:
85
return ("Failed to send(2) cpuset information");
86
case FAILURE_DEADLK:
87
return ("Deadlock hit trying to attach to jail");
88
case FAILURE_ATTACH:
89
return ("jail_attach(2) failed");
90
case FAILURE_BADAFFIN:
91
return ("Unexpected post-attach affinity");
92
case FAILURE_SUCCESS:
93
return ("jail_attach(2) succeeded, but should have failed.");
94
default:
95
return (NULL);
96
}
97
}
98
99
static void
100
skip_ltncpu(int ncpu, cpuset_t *mask)
101
{
102
103
CPU_ZERO(mask);
104
ATF_REQUIRE_EQ(0, cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
105
-1, sizeof(*mask), mask));
106
if (CPU_COUNT(mask) < ncpu)
107
atf_tc_skip("Test requires %d or more cores.", ncpu);
108
}
109
110
ATF_TC(newset);
111
ATF_TC_HEAD(newset, tc)
112
{
113
atf_tc_set_md_var(tc, "descr", "Test cpuset(2)");
114
}
115
ATF_TC_BODY(newset, tc)
116
{
117
cpusetid_t nsetid, setid, qsetid;
118
119
/* Obtain our initial set id. */
120
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1,
121
&setid));
122
123
/* Create a new one. */
124
ATF_REQUIRE_EQ(0, cpuset(&nsetid));
125
ATF_CHECK(nsetid != setid);
126
127
/* Query id again, make sure it's equal to the one we just got. */
128
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1,
129
&qsetid));
130
ATF_CHECK_EQ(nsetid, qsetid);
131
}
132
133
ATF_TC(transient);
134
ATF_TC_HEAD(transient, tc)
135
{
136
atf_tc_set_md_var(tc, "descr",
137
"Test that transient cpusets are freed.");
138
}
139
ATF_TC_BODY(transient, tc)
140
{
141
cpusetid_t isetid, scratch, setid;
142
143
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1,
144
&isetid));
145
146
ATF_REQUIRE_EQ(0, cpuset(&setid));
147
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET,
148
setid, &scratch));
149
150
/*
151
* Return back to our initial cpuset; the kernel should free the cpuset
152
* we just created.
153
*/
154
ATF_REQUIRE_EQ(0, cpuset_setid(CPU_WHICH_PID, -1, isetid));
155
ATF_REQUIRE_EQ(-1, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET,
156
setid, &scratch));
157
ATF_CHECK_EQ(ESRCH, errno);
158
}
159
160
ATF_TC(deadlk);
161
ATF_TC_HEAD(deadlk, tc)
162
{
163
atf_tc_set_md_var(tc, "descr", "Test against disjoint cpusets.");
164
atf_tc_set_md_var(tc, "require.user", "root");
165
}
166
ATF_TC_BODY(deadlk, tc)
167
{
168
cpusetid_t setid;
169
cpuset_t dismask, mask, omask;
170
int fcpu, i, found, ncpu, second;
171
172
/* Make sure we have 3 cpus, so we test partial overlap. */
173
skip_ltncpu(3, &omask);
174
175
ATF_REQUIRE_EQ(0, cpuset(&setid));
176
CPU_ZERO(&mask);
177
CPU_ZERO(&dismask);
178
CPU_COPY(&omask, &mask);
179
CPU_COPY(&omask, &dismask);
180
fcpu = CPU_FFS(&mask);
181
ncpu = CPU_COUNT(&mask);
182
183
/*
184
* Turn off all but the first two for mask, turn off the first for
185
* dismask and turn them all off for both after the third.
186
*/
187
for (i = fcpu - 1, found = 0; i < CPU_MAXSIZE && found != ncpu; i++) {
188
if (CPU_ISSET(i, &omask)) {
189
found++;
190
if (found == 1) {
191
CPU_CLR(i, &dismask);
192
} else if (found == 2) {
193
second = i;
194
} else if (found >= 3) {
195
CPU_CLR(i, &mask);
196
if (found > 3)
197
CPU_CLR(i, &dismask);
198
}
199
}
200
}
201
202
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
203
-1, sizeof(mask), &mask));
204
205
/* Must be a strict subset! */
206
ATF_REQUIRE_EQ(-1, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
207
-1, sizeof(dismask), &dismask));
208
ATF_REQUIRE_EQ(EINVAL, errno);
209
210
/*
211
* We'll set our anonymous set to the 0,1 set that currently matches
212
* the process. If we then set the process to the 1,2 set that's in
213
* dismask, we should then personally be restricted down to the single
214
* overlapping CPOU.
215
*/
216
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
217
-1, sizeof(mask), &mask));
218
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
219
-1, sizeof(dismask), &dismask));
220
ATF_REQUIRE_EQ(0, cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
221
-1, sizeof(mask), &mask));
222
ATF_REQUIRE_EQ(1, CPU_COUNT(&mask));
223
ATF_REQUIRE(CPU_ISSET(second, &mask));
224
225
/*
226
* Finally, clearing the overlap and attempting to set the process
227
* cpuset to a completely disjoint mask should fail, because this
228
* process will then not have anything to run on.
229
*/
230
CPU_CLR(second, &dismask);
231
ATF_REQUIRE_EQ(-1, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
232
-1, sizeof(dismask), &dismask));
233
ATF_REQUIRE_EQ(EDEADLK, errno);
234
}
235
236
static int
237
do_jail(int sock)
238
{
239
struct jail_test_info info;
240
struct iovec iov[2];
241
char *name;
242
int error;
243
244
if (asprintf(&name, "cpuset_%d", getpid()) == -1)
245
_exit(42);
246
247
iov[0].iov_base = "name";
248
iov[0].iov_len = 5;
249
250
iov[1].iov_base = name;
251
iov[1].iov_len = strlen(name) + 1;
252
253
if (jail_set(iov, 2, JAIL_CREATE | JAIL_ATTACH) < 0)
254
return (FAILURE_JAIL);
255
256
/* Record parameters, kick them over, then make a swift exit. */
257
CPU_ZERO(&info.jail_tidmask);
258
error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
259
-1, sizeof(info.jail_tidmask), &info.jail_tidmask);
260
if (error != 0)
261
return (FAILURE_MASK);
262
263
error = cpuset_getid(CPU_LEVEL_ROOT, CPU_WHICH_TID, -1,
264
&info.jail_cpuset);
265
if (error != 0)
266
return (FAILURE_JAILSET);
267
error = cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1,
268
&info.jail_child_cpuset);
269
if (error != 0)
270
return (FAILURE_PIDSET);
271
if (send(sock, &info, sizeof(info), 0) != sizeof(info))
272
return (FAILURE_SEND);
273
return (0);
274
}
275
276
static void
277
do_jail_test(int ncpu, bool newset, jail_test_cb prologue,
278
jail_test_cb epilogue)
279
{
280
struct jail_test_cb_params cbp;
281
const char *errstr;
282
pid_t pid;
283
int error, sock, sockpair[2], status;
284
285
memset(&cbp.info, '\0', sizeof(cbp.info));
286
287
skip_ltncpu(ncpu, &cbp.mask);
288
289
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
290
&cbp.rootid));
291
if (newset)
292
ATF_REQUIRE_EQ(0, cpuset(&cbp.setid));
293
else
294
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
295
-1, &cbp.setid));
296
/* Special hack for prison0; it uses cpuset 1 as the root. */
297
if (cbp.rootid == 0)
298
cbp.rootid = 1;
299
300
/* Not every test needs early setup. */
301
if (prologue != NULL)
302
(*prologue)(&cbp);
303
304
ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sockpair));
305
ATF_REQUIRE((pid = fork()) != -1);
306
307
if (pid == 0) {
308
/* Child */
309
close(sockpair[SP_PARENT]);
310
sock = sockpair[SP_CHILD];
311
312
_exit(do_jail(sock));
313
} else {
314
/* Parent */
315
sock = sockpair[SP_PARENT];
316
close(sockpair[SP_CHILD]);
317
318
while ((error = waitpid(pid, &status, 0)) == -1 &&
319
errno == EINTR) {
320
}
321
322
ATF_REQUIRE_EQ(sizeof(cbp.info), recv(sock, &cbp.info,
323
sizeof(cbp.info), 0));
324
325
/* Sanity check the exit info. */
326
ATF_REQUIRE_EQ(pid, error);
327
ATF_REQUIRE(WIFEXITED(status));
328
if (WEXITSTATUS(status) != 0) {
329
errstr = do_jail_errstr(WEXITSTATUS(status));
330
if (errstr != NULL)
331
atf_tc_fail("%s", errstr);
332
else
333
atf_tc_fail("Unknown error '%d'",
334
WEXITSTATUS(status));
335
}
336
337
epilogue(&cbp);
338
}
339
}
340
341
static void
342
jail_attach_mutate_pro(struct jail_test_cb_params *cbp)
343
{
344
cpuset_t *mask;
345
int count;
346
347
mask = &cbp->mask;
348
349
/* Knock out the first cpu. */
350
count = CPU_COUNT(mask);
351
CPU_CLR(CPU_FFS(mask) - 1, mask);
352
ATF_REQUIRE_EQ(count - 1, CPU_COUNT(mask));
353
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
354
-1, sizeof(*mask), mask));
355
}
356
357
static void
358
jail_attach_newbase_epi(struct jail_test_cb_params *cbp)
359
{
360
struct jail_test_info *info;
361
cpuset_t *mask;
362
363
info = &cbp->info;
364
mask = &cbp->mask;
365
366
/*
367
* The rootid test has been thrown in because a bug was discovered
368
* where any newly derived cpuset during attach would be parented to
369
* the wrong cpuset. Otherwise, we should observe that a new cpuset
370
* has been created for this process.
371
*/
372
ATF_REQUIRE(info->jail_cpuset != cbp->rootid);
373
ATF_REQUIRE(info->jail_cpuset != cbp->setid);
374
ATF_REQUIRE(info->jail_cpuset != info->jail_child_cpuset);
375
ATF_REQUIRE_EQ(0, CPU_CMP(mask, &info->jail_tidmask));
376
}
377
378
ATF_TC(jail_attach_newbase);
379
ATF_TC_HEAD(jail_attach_newbase, tc)
380
{
381
atf_tc_set_md_var(tc, "descr",
382
"Test jail attachment effect on affinity with a new base cpuset.");
383
atf_tc_set_md_var(tc, "require.user", "root");
384
}
385
ATF_TC_BODY(jail_attach_newbase, tc)
386
{
387
388
/* Need >= 2 cpus to test restriction. */
389
do_jail_test(2, true, &jail_attach_mutate_pro,
390
&jail_attach_newbase_epi);
391
}
392
393
ATF_TC(jail_attach_newbase_plain);
394
ATF_TC_HEAD(jail_attach_newbase_plain, tc)
395
{
396
atf_tc_set_md_var(tc, "descr",
397
"Test jail attachment effect on affinity with a new, unmodified base cpuset.");
398
atf_tc_set_md_var(tc, "require.user", "root");
399
}
400
ATF_TC_BODY(jail_attach_newbase_plain, tc)
401
{
402
403
do_jail_test(2, true, NULL, &jail_attach_newbase_epi);
404
}
405
406
/*
407
* Generic epilogue for tests that are expecting to use the jail's root cpuset
408
* with their own mask, whether that's been modified or not.
409
*/
410
static void
411
jail_attach_jset_epi(struct jail_test_cb_params *cbp)
412
{
413
struct jail_test_info *info;
414
cpuset_t *mask;
415
416
info = &cbp->info;
417
mask = &cbp->mask;
418
419
ATF_REQUIRE(info->jail_cpuset != cbp->setid);
420
ATF_REQUIRE_EQ(info->jail_cpuset, info->jail_child_cpuset);
421
ATF_REQUIRE_EQ(0, CPU_CMP(mask, &info->jail_tidmask));
422
}
423
424
ATF_TC(jail_attach_prevbase);
425
ATF_TC_HEAD(jail_attach_prevbase, tc)
426
{
427
atf_tc_set_md_var(tc, "descr",
428
"Test jail attachment effect on affinity without a new base.");
429
atf_tc_set_md_var(tc, "require.user", "root");
430
}
431
ATF_TC_BODY(jail_attach_prevbase, tc)
432
{
433
434
do_jail_test(2, false, &jail_attach_mutate_pro, &jail_attach_jset_epi);
435
}
436
437
static void
438
jail_attach_plain_pro(struct jail_test_cb_params *cbp)
439
{
440
441
if (cbp->setid != cbp->rootid)
442
atf_tc_skip("Must be running with the root cpuset.");
443
}
444
445
ATF_TC(jail_attach_plain);
446
ATF_TC_HEAD(jail_attach_plain, tc)
447
{
448
atf_tc_set_md_var(tc, "descr",
449
"Test jail attachment effect on affinity without specialization.");
450
atf_tc_set_md_var(tc, "require.user", "root");
451
}
452
ATF_TC_BODY(jail_attach_plain, tc)
453
{
454
455
do_jail_test(1, false, &jail_attach_plain_pro, &jail_attach_jset_epi);
456
}
457
458
static int
459
jail_attach_disjoint_newjail(int fd)
460
{
461
struct iovec iov[2];
462
char *name;
463
int jid;
464
465
if (asprintf(&name, "cpuset_%d", getpid()) == -1)
466
_exit(42);
467
468
iov[0].iov_base = "name";
469
iov[0].iov_len = sizeof("name");
470
471
iov[1].iov_base = name;
472
iov[1].iov_len = strlen(name) + 1;
473
474
if ((jid = jail_set(iov, 2, JAIL_CREATE | JAIL_ATTACH)) < 0)
475
return (FAILURE_JAIL);
476
477
/* Signal that we're ready. */
478
write(fd, &jid, sizeof(jid));
479
for (;;) {
480
/* Spin */
481
}
482
}
483
484
static int
485
wait_jail(int fd, int pfd)
486
{
487
fd_set lset;
488
struct timeval tv;
489
int error, jid, maxfd;
490
491
FD_ZERO(&lset);
492
FD_SET(fd, &lset);
493
FD_SET(pfd, &lset);
494
495
maxfd = MAX(fd, pfd);
496
497
tv.tv_sec = 5;
498
tv.tv_usec = 0;
499
500
/* Wait for jid to be written. */
501
do {
502
error = select(maxfd + 1, &lset, NULL, NULL, &tv);
503
} while (error == -1 && errno == EINTR);
504
505
if (error == 0) {
506
atf_tc_fail("Jail creator did not respond in time.");
507
}
508
509
ATF_REQUIRE_MSG(error > 0, "Unexpected error %d from select()", errno);
510
511
if (FD_ISSET(pfd, &lset)) {
512
/* Process died */
513
atf_tc_fail("Jail creator died unexpectedly.");
514
}
515
516
ATF_REQUIRE(FD_ISSET(fd, &lset));
517
ATF_REQUIRE_EQ(sizeof(jid), recv(fd, &jid, sizeof(jid), 0));
518
519
return (jid);
520
}
521
522
static int
523
try_attach_child(int jid, cpuset_t *expected_mask)
524
{
525
cpuset_t mask;
526
527
if (jail_attach(jid) == -1) {
528
if (errno == EDEADLK)
529
return (FAILURE_DEADLK);
530
return (FAILURE_ATTACH);
531
}
532
533
if (expected_mask == NULL)
534
return (FAILURE_SUCCESS);
535
536
/* If we had an expected mask, check it against the new process mask. */
537
CPU_ZERO(&mask);
538
if (cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID,
539
-1, sizeof(mask), &mask) != 0) {
540
return (FAILURE_MASK);
541
}
542
543
if (CPU_CMP(expected_mask, &mask) != 0)
544
return (FAILURE_BADAFFIN);
545
546
return (0);
547
}
548
549
static void
550
try_attach(int jid, cpuset_t *expected_mask)
551
{
552
const char *errstr;
553
pid_t pid;
554
int error, fail, status;
555
556
ATF_REQUIRE(expected_mask != NULL);
557
ATF_REQUIRE((pid = fork()) != -1);
558
if (pid == 0)
559
_exit(try_attach_child(jid, expected_mask));
560
561
while ((error = waitpid(pid, &status, 0)) == -1 && errno == EINTR) {
562
/* Try again. */
563
}
564
565
/* Sanity check the exit info. */
566
ATF_REQUIRE_EQ(pid, error);
567
ATF_REQUIRE(WIFEXITED(status));
568
if ((fail = WEXITSTATUS(status)) != 0) {
569
errstr = do_jail_errstr(fail);
570
if (errstr != NULL)
571
atf_tc_fail("%s", errstr);
572
else
573
atf_tc_fail("Unknown error '%d'", WEXITSTATUS(status));
574
}
575
}
576
577
ATF_TC(jail_attach_disjoint);
578
ATF_TC_HEAD(jail_attach_disjoint, tc)
579
{
580
atf_tc_set_md_var(tc, "descr",
581
"Test root attachment into completely disjoint jail cpuset.");
582
atf_tc_set_md_var(tc, "require.user", "root");
583
}
584
ATF_TC_BODY(jail_attach_disjoint, tc)
585
{
586
cpuset_t smask, jmask;
587
int sockpair[2];
588
cpusetid_t setid;
589
pid_t pid;
590
int fcpu, jid, pfd, sock, scpu;
591
592
ATF_REQUIRE_EQ(0, cpuset(&setid));
593
594
skip_ltncpu(2, &jmask);
595
fcpu = CPU_FFS(&jmask) - 1;
596
ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sockpair));
597
598
/* We'll wait on the procdesc, too, so we can fail faster if it dies. */
599
ATF_REQUIRE((pid = pdfork(&pfd, 0)) != -1);
600
601
if (pid == 0) {
602
/* First child sets up the jail. */
603
sock = sockpair[SP_CHILD];
604
close(sockpair[SP_PARENT]);
605
606
_exit(jail_attach_disjoint_newjail(sock));
607
}
608
609
close(sockpair[SP_CHILD]);
610
sock = sockpair[SP_PARENT];
611
612
ATF_REQUIRE((jid = wait_jail(sock, pfd)) > 0);
613
614
/*
615
* This process will be clamped down to the first cpu, while the jail
616
* will simply have the first CPU removed to make it a completely
617
* disjoint operation.
618
*/
619
CPU_ZERO(&smask);
620
CPU_SET(fcpu, &smask);
621
CPU_CLR(fcpu, &jmask);
622
623
/*
624
* We'll test with the first and second cpu set as well. Only the
625
* second cpu should be used.
626
*/
627
scpu = CPU_FFS(&jmask) - 1;
628
629
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_ROOT, CPU_WHICH_JAIL,
630
jid, sizeof(jmask), &jmask));
631
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET,
632
setid, sizeof(smask), &smask));
633
634
try_attach(jid, &jmask);
635
636
CPU_SET(scpu, &smask);
637
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET,
638
setid, sizeof(smask), &smask));
639
640
CPU_CLR(fcpu, &smask);
641
try_attach(jid, &smask);
642
}
643
644
ATF_TC(badparent);
645
ATF_TC_HEAD(badparent, tc)
646
{
647
atf_tc_set_md_var(tc, "descr",
648
"Test parent assignment when assigning a new cpuset.");
649
}
650
ATF_TC_BODY(badparent, tc)
651
{
652
cpuset_t mask;
653
cpusetid_t finalsetid, origsetid, setid;
654
655
/* Need to mask off at least one CPU. */
656
skip_ltncpu(2, &mask);
657
658
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1,
659
&origsetid));
660
661
ATF_REQUIRE_EQ(0, cpuset(&setid));
662
663
/*
664
* Mask off the first CPU, then we'll reparent ourselves to our original
665
* set.
666
*/
667
CPU_CLR(CPU_FFS(&mask) - 1, &mask);
668
ATF_REQUIRE_EQ(0, cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
669
-1, sizeof(mask), &mask));
670
671
ATF_REQUIRE_EQ(0, cpuset_setid(CPU_WHICH_PID, -1, origsetid));
672
ATF_REQUIRE_EQ(0, cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, -1,
673
&finalsetid));
674
675
ATF_REQUIRE_EQ(finalsetid, origsetid);
676
}
677
678
ATF_TP_ADD_TCS(tp)
679
{
680
681
ATF_TP_ADD_TC(tp, newset);
682
ATF_TP_ADD_TC(tp, transient);
683
ATF_TP_ADD_TC(tp, deadlk);
684
ATF_TP_ADD_TC(tp, jail_attach_newbase);
685
ATF_TP_ADD_TC(tp, jail_attach_newbase_plain);
686
ATF_TP_ADD_TC(tp, jail_attach_prevbase);
687
ATF_TP_ADD_TC(tp, jail_attach_plain);
688
ATF_TP_ADD_TC(tp, jail_attach_disjoint);
689
ATF_TP_ADD_TC(tp, badparent);
690
return (atf_no_error());
691
}
692
693