xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_mlock.c (revision 631607ac2965e8c6dcc0f21effc9b36fcb530558)
1640235e2SEnji Cooper /* $NetBSD: t_mlock.c,v 1.6 2016/08/09 12:02:44 kre Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2012 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper  * by Jukka Ruohonen.
957718be8SEnji Cooper  *
1057718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper  * are met:
1357718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper  *
1957718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper #include <sys/cdefs.h>
32640235e2SEnji Cooper __RCSID("$NetBSD: t_mlock.c,v 1.6 2016/08/09 12:02:44 kre Exp $");
3357718be8SEnji Cooper 
3455fd0faaSEnji Cooper #ifdef __FreeBSD__
3539a3103bSEnji Cooper #include <sys/param.h> /* NetBSD requires sys/param.h for sysctl(3), unlike FreeBSD */
3655fd0faaSEnji Cooper #endif
3757718be8SEnji Cooper #include <sys/mman.h>
3857718be8SEnji Cooper #include <sys/resource.h>
3957718be8SEnji Cooper #include <sys/sysctl.h>
4057718be8SEnji Cooper #include <sys/wait.h>
4157718be8SEnji Cooper 
4257718be8SEnji Cooper #include <errno.h>
4357718be8SEnji Cooper #include <atf-c.h>
4457718be8SEnji Cooper #include <stdint.h>
4557718be8SEnji Cooper #include <stdio.h>
4657718be8SEnji Cooper #include <stdlib.h>
4757718be8SEnji Cooper #include <unistd.h>
4857718be8SEnji Cooper 
4955fd0faaSEnji Cooper #ifdef __FreeBSD__
508e62f841SEnji Cooper #include <limits.h>
5155fd0faaSEnji Cooper #define _KMEMUSER
5255fd0faaSEnji Cooper #include <machine/vmparam.h>
53710542dfSBryan Drewery 
54*54a3a114SMark Johnston void set_vm_max_wired(u_long);
55710542dfSBryan Drewery void restore_vm_max_wired(void);
5655fd0faaSEnji Cooper #endif
5755fd0faaSEnji Cooper 
5857718be8SEnji Cooper static long page = 0;
5957718be8SEnji Cooper 
6057718be8SEnji Cooper ATF_TC(mlock_clip);
ATF_TC_HEAD(mlock_clip,tc)6157718be8SEnji Cooper ATF_TC_HEAD(mlock_clip, tc)
6257718be8SEnji Cooper {
6357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test with mlock(2) that UVM only "
6457718be8SEnji Cooper 	    "clips if the clip address is within the entry (PR kern/44788)");
6557718be8SEnji Cooper }
6657718be8SEnji Cooper 
ATF_TC_BODY(mlock_clip,tc)6757718be8SEnji Cooper ATF_TC_BODY(mlock_clip, tc)
6857718be8SEnji Cooper {
6957718be8SEnji Cooper 	void *buf;
7057718be8SEnji Cooper 
7157718be8SEnji Cooper 	buf = malloc(page);
7257718be8SEnji Cooper 	ATF_REQUIRE(buf != NULL);
7357718be8SEnji Cooper 
7457718be8SEnji Cooper 	if (page < 1024)
7557718be8SEnji Cooper 		atf_tc_skip("page size too small");
7657718be8SEnji Cooper 
7757718be8SEnji Cooper 	for (size_t i = page; i >= 1; i = i - 1024) {
7857718be8SEnji Cooper 		(void)mlock(buf, page - i);
7957718be8SEnji Cooper 		(void)munlock(buf, page - i);
8057718be8SEnji Cooper 	}
8157718be8SEnji Cooper 
8257718be8SEnji Cooper 	free(buf);
8357718be8SEnji Cooper }
8457718be8SEnji Cooper 
858e62f841SEnji Cooper #ifdef __FreeBSD__
868e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_err);
878e62f841SEnji Cooper #else
8857718be8SEnji Cooper ATF_TC(mlock_err);
898e62f841SEnji Cooper #endif
ATF_TC_HEAD(mlock_err,tc)9057718be8SEnji Cooper ATF_TC_HEAD(mlock_err, tc)
9157718be8SEnji Cooper {
9257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
9357718be8SEnji Cooper 	    "Test error conditions in mlock(2) and munlock(2)");
948e62f841SEnji Cooper #ifdef __FreeBSD__
958e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
968e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
978e62f841SEnji Cooper #endif
9857718be8SEnji Cooper }
9957718be8SEnji Cooper 
ATF_TC_BODY(mlock_err,tc)10057718be8SEnji Cooper ATF_TC_BODY(mlock_err, tc)
10157718be8SEnji Cooper {
10255fd0faaSEnji Cooper #ifdef __NetBSD__
10357718be8SEnji Cooper 	unsigned long vmin = 0;
10457718be8SEnji Cooper 	size_t len = sizeof(vmin);
10555fd0faaSEnji Cooper #endif
106ca20f8ecSRuslan Bukin #if !defined(__aarch64__) && !defined(__riscv)
10757718be8SEnji Cooper 	void *invalid_ptr;
10894098ab7SAndrew Turner #endif
109640235e2SEnji Cooper 	void *buf;
11057718be8SEnji Cooper 
11155fd0faaSEnji Cooper #ifdef __FreeBSD__
1128e62f841SEnji Cooper 	/* Set max_wired really really high to avoid EAGAIN */
1138e62f841SEnji Cooper 	set_vm_max_wired(INT_MAX);
11455fd0faaSEnji Cooper #else
11557718be8SEnji Cooper 	if (sysctlbyname("vm.minaddress", &vmin, &len, NULL, 0) != 0)
11657718be8SEnji Cooper 		atf_tc_fail("failed to read vm.minaddress");
117640235e2SEnji Cooper 	/*
118640235e2SEnji Cooper 	 * Any bad address must return ENOMEM (for lock & unlock)
119640235e2SEnji Cooper 	 */
120640235e2SEnji Cooper 	errno = 0;
121640235e2SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, mlock(NULL, page) == -1);
12255fd0faaSEnji Cooper #endif
12357718be8SEnji Cooper 
12457718be8SEnji Cooper 	errno = 0;
125640235e2SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, mlock((char *)0, page) == -1);
12657718be8SEnji Cooper 
12757718be8SEnji Cooper 	errno = 0;
128640235e2SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, munlock(NULL, page) == -1);
12957718be8SEnji Cooper 
13057718be8SEnji Cooper 	errno = 0;
131640235e2SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, munlock((char *)0, page) == -1);
13257718be8SEnji Cooper 
13376f9d275SAlan Somers #ifdef __FreeBSD__
13476f9d275SAlan Somers 	/* Wrap around should return EINVAL */
13576f9d275SAlan Somers 	errno = 0;
13676f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(EINVAL, mlock((char *)-1, page) == -1);
13776f9d275SAlan Somers 	errno = 0;
13876f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(EINVAL, munlock((char *)-1, page) == -1);
13976f9d275SAlan Somers #else
14076f9d275SAlan Somers 	errno = 0;
14176f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(ENOMEM, mlock((char *)-1, page) == -1);
14257718be8SEnji Cooper 	errno = 0;
143640235e2SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, munlock((char *)-1, page) == -1);
14476f9d275SAlan Somers #endif
145640235e2SEnji Cooper 
14676f9d275SAlan Somers 	buf = malloc(page);	/* Get a valid address */
147640235e2SEnji Cooper 	ATF_REQUIRE(buf != NULL);
14876f9d275SAlan Somers #ifdef __FreeBSD__
14957718be8SEnji Cooper 	errno = 0;
15076f9d275SAlan Somers 	/* Wrap around should return EINVAL */
15176f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(EINVAL, mlock(buf, -page) == -1);
15276f9d275SAlan Somers 	errno = 0;
15376f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(EINVAL, munlock(buf, -page) == -1);
15476f9d275SAlan Somers #else
15576f9d275SAlan Somers 	errno = 0;
15676f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(ENOMEM, mlock(buf, -page) == -1);
15776f9d275SAlan Somers 	errno = 0;
15876f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(ENOMEM, munlock(buf, -page) == -1);
15976f9d275SAlan Somers #endif
16076f9d275SAlan Somers 	(void)free(buf);
16157718be8SEnji Cooper 
162b7b46892SRuslan Bukin /* There is no sbrk on AArch64 and RISC-V */
163ca20f8ecSRuslan Bukin #if !defined(__aarch64__) && !defined(__riscv)
16457718be8SEnji Cooper 	/*
16557718be8SEnji Cooper 	 * Try to create a pointer to an unmapped page - first after current
16657718be8SEnji Cooper 	 * brk will likely do.
16757718be8SEnji Cooper 	 */
16857718be8SEnji Cooper 	invalid_ptr = (void*)(((uintptr_t)sbrk(0)+page) & ~(page-1));
16957718be8SEnji Cooper 	printf("testing with (hopefully) invalid pointer %p\n", invalid_ptr);
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 	errno = 0;
17257718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, mlock(invalid_ptr, page) == -1);
17357718be8SEnji Cooper 
17457718be8SEnji Cooper 	errno = 0;
17557718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, munlock(invalid_ptr, page) == -1);
17694098ab7SAndrew Turner #endif
17757718be8SEnji Cooper }
17857718be8SEnji Cooper 
1798e62f841SEnji Cooper #ifdef __FreeBSD__
ATF_TC_CLEANUP(mlock_err,tc)1808e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_err, tc)
1818e62f841SEnji Cooper {
1828e62f841SEnji Cooper 
1838e62f841SEnji Cooper 	restore_vm_max_wired();
1848e62f841SEnji Cooper }
1858e62f841SEnji Cooper #endif
1868e62f841SEnji Cooper 
18757718be8SEnji Cooper ATF_TC(mlock_limits);
ATF_TC_HEAD(mlock_limits,tc)18857718be8SEnji Cooper ATF_TC_HEAD(mlock_limits, tc)
18957718be8SEnji Cooper {
19057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test system limits with mlock(2)");
19157718be8SEnji Cooper }
19257718be8SEnji Cooper 
ATF_TC_BODY(mlock_limits,tc)19357718be8SEnji Cooper ATF_TC_BODY(mlock_limits, tc)
19457718be8SEnji Cooper {
19557718be8SEnji Cooper 	struct rlimit res;
19657718be8SEnji Cooper 	void *buf;
19757718be8SEnji Cooper 	pid_t pid;
19857718be8SEnji Cooper 	int sta;
19957718be8SEnji Cooper 
20057718be8SEnji Cooper 	buf = malloc(page);
20157718be8SEnji Cooper 	ATF_REQUIRE(buf != NULL);
20257718be8SEnji Cooper 
20357718be8SEnji Cooper 	pid = fork();
20457718be8SEnji Cooper 	ATF_REQUIRE(pid >= 0);
20557718be8SEnji Cooper 
20657718be8SEnji Cooper 	if (pid == 0) {
20757718be8SEnji Cooper 
20857718be8SEnji Cooper 		for (ssize_t i = page; i >= 2; i -= 100) {
20957718be8SEnji Cooper 
21057718be8SEnji Cooper 			res.rlim_cur = i - 1;
21157718be8SEnji Cooper 			res.rlim_max = i - 1;
21257718be8SEnji Cooper 
21357718be8SEnji Cooper 			(void)fprintf(stderr, "trying to lock %zd bytes "
21457718be8SEnji Cooper 			    "with %zu byte limit\n", i, (size_t)res.rlim_cur);
21557718be8SEnji Cooper 
21657718be8SEnji Cooper 			if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
21757718be8SEnji Cooper 				_exit(EXIT_FAILURE);
21857718be8SEnji Cooper 
21957718be8SEnji Cooper 			errno = 0;
22057718be8SEnji Cooper 
22155fd0faaSEnji Cooper #ifdef __FreeBSD__
22255fd0faaSEnji Cooper 			/*
22355fd0faaSEnji Cooper 			 * NetBSD doesn't conform to POSIX with ENOMEM requirement;
22455fd0faaSEnji Cooper 			 * FreeBSD does.
22555fd0faaSEnji Cooper 			 *
22655fd0faaSEnji Cooper 			 * See: NetBSD PR # kern/48962 for more details.
22755fd0faaSEnji Cooper 			 */
22855fd0faaSEnji Cooper 			if (mlock(buf, i) != -1 || errno != ENOMEM) {
22955fd0faaSEnji Cooper #else
23057718be8SEnji Cooper 			if (mlock(buf, i) != -1 || errno != EAGAIN) {
23155fd0faaSEnji Cooper #endif
23257718be8SEnji Cooper 				(void)munlock(buf, i);
23357718be8SEnji Cooper 				_exit(EXIT_FAILURE);
23457718be8SEnji Cooper 			}
23557718be8SEnji Cooper 		}
23657718be8SEnji Cooper 
23757718be8SEnji Cooper 		_exit(EXIT_SUCCESS);
23857718be8SEnji Cooper 	}
23957718be8SEnji Cooper 
24057718be8SEnji Cooper 	(void)wait(&sta);
24157718be8SEnji Cooper 
24257718be8SEnji Cooper 	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
24357718be8SEnji Cooper 		atf_tc_fail("mlock(2) locked beyond system limits");
24457718be8SEnji Cooper 
24557718be8SEnji Cooper 	free(buf);
24657718be8SEnji Cooper }
24757718be8SEnji Cooper 
2488e62f841SEnji Cooper #ifdef __FreeBSD__
2498e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_mmap);
2508e62f841SEnji Cooper #else
25157718be8SEnji Cooper ATF_TC(mlock_mmap);
2528e62f841SEnji Cooper #endif
25357718be8SEnji Cooper ATF_TC_HEAD(mlock_mmap, tc)
25457718be8SEnji Cooper {
25557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test mlock(2)-mmap(2) interaction");
2568e62f841SEnji Cooper #ifdef __FreeBSD__
2578e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
2588e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
2598e62f841SEnji Cooper #endif
26057718be8SEnji Cooper }
26157718be8SEnji Cooper 
26257718be8SEnji Cooper ATF_TC_BODY(mlock_mmap, tc)
26357718be8SEnji Cooper {
26455fd0faaSEnji Cooper #ifdef __NetBSD__
26557718be8SEnji Cooper 	static const int flags = MAP_ANON | MAP_PRIVATE | MAP_WIRED;
26655fd0faaSEnji Cooper #else
26755fd0faaSEnji Cooper 	static const int flags = MAP_ANON | MAP_PRIVATE;
26855fd0faaSEnji Cooper #endif
26957718be8SEnji Cooper 	void *buf;
27057718be8SEnji Cooper 
2718e62f841SEnji Cooper #ifdef __FreeBSD__
2728e62f841SEnji Cooper 	/* Set max_wired really really high to avoid EAGAIN */
2738e62f841SEnji Cooper 	set_vm_max_wired(INT_MAX);
2748e62f841SEnji Cooper #endif
2758e62f841SEnji Cooper 
27657718be8SEnji Cooper 	/*
27757718be8SEnji Cooper 	 * Make a wired RW mapping and check that mlock(2)
27857718be8SEnji Cooper 	 * does not fail for the (already locked) mapping.
27957718be8SEnji Cooper 	 */
28057718be8SEnji Cooper 	buf = mmap(NULL, page, PROT_READ | PROT_WRITE, flags, -1, 0);
28157718be8SEnji Cooper 
28257718be8SEnji Cooper 	ATF_REQUIRE(buf != MAP_FAILED);
28355fd0faaSEnji Cooper #ifdef __FreeBSD__
28455fd0faaSEnji Cooper 	/*
28555fd0faaSEnji Cooper 	 * The duplicate mlock call is added to ensure that the call works
28655fd0faaSEnji Cooper 	 * as described above without MAP_WIRED support.
28755fd0faaSEnji Cooper 	 */
28855fd0faaSEnji Cooper 	ATF_REQUIRE(mlock(buf, page) == 0);
28955fd0faaSEnji Cooper #endif
29057718be8SEnji Cooper 	ATF_REQUIRE(mlock(buf, page) == 0);
29157718be8SEnji Cooper 	ATF_REQUIRE(munlock(buf, page) == 0);
29257718be8SEnji Cooper 	ATF_REQUIRE(munmap(buf, page) == 0);
29357718be8SEnji Cooper 	ATF_REQUIRE(munlock(buf, page) != 0);
29457718be8SEnji Cooper 
29557718be8SEnji Cooper 	/*
29657718be8SEnji Cooper 	 * But it should be impossible to mlock(2) a PROT_NONE mapping.
29757718be8SEnji Cooper 	 */
29857718be8SEnji Cooper 	buf = mmap(NULL, page, PROT_NONE, flags, -1, 0);
29957718be8SEnji Cooper 
30057718be8SEnji Cooper 	ATF_REQUIRE(buf != MAP_FAILED);
30155fd0faaSEnji Cooper #ifdef __FreeBSD__
30255fd0faaSEnji Cooper 	ATF_REQUIRE_ERRNO(ENOMEM, mlock(buf, page) != 0);
30355fd0faaSEnji Cooper #else
30457718be8SEnji Cooper 	ATF_REQUIRE(mlock(buf, page) != 0);
30555fd0faaSEnji Cooper #endif
30657718be8SEnji Cooper 	ATF_REQUIRE(munmap(buf, page) == 0);
30757718be8SEnji Cooper }
30857718be8SEnji Cooper 
3098e62f841SEnji Cooper #ifdef __FreeBSD__
3108e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_mmap, tc)
3118e62f841SEnji Cooper {
3128e62f841SEnji Cooper 
3138e62f841SEnji Cooper 	restore_vm_max_wired();
3148e62f841SEnji Cooper }
3158e62f841SEnji Cooper #endif
3168e62f841SEnji Cooper 
3178e62f841SEnji Cooper #ifdef __FreeBSD__
3188e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_nested);
3198e62f841SEnji Cooper #else
32057718be8SEnji Cooper ATF_TC(mlock_nested);
3218e62f841SEnji Cooper #endif
32257718be8SEnji Cooper ATF_TC_HEAD(mlock_nested, tc)
32357718be8SEnji Cooper {
32457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
32557718be8SEnji Cooper 	    "Test that consecutive mlock(2) calls succeed");
3268e62f841SEnji Cooper #ifdef __FreeBSD__
3278e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
3288e62f841SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
3298e62f841SEnji Cooper #endif
33057718be8SEnji Cooper }
33157718be8SEnji Cooper 
33257718be8SEnji Cooper ATF_TC_BODY(mlock_nested, tc)
33357718be8SEnji Cooper {
33457718be8SEnji Cooper 	const size_t maxiter = 100;
33557718be8SEnji Cooper 	void *buf;
33657718be8SEnji Cooper 
3378e62f841SEnji Cooper #ifdef __FreeBSD__
3388e62f841SEnji Cooper 	/* Set max_wired really really high to avoid EAGAIN */
3398e62f841SEnji Cooper 	set_vm_max_wired(INT_MAX);
3408e62f841SEnji Cooper #endif
3418e62f841SEnji Cooper 
34257718be8SEnji Cooper 	buf = malloc(page);
34357718be8SEnji Cooper 	ATF_REQUIRE(buf != NULL);
34457718be8SEnji Cooper 
34557718be8SEnji Cooper 	for (size_t i = 0; i < maxiter; i++)
34657718be8SEnji Cooper 		ATF_REQUIRE(mlock(buf, page) == 0);
34757718be8SEnji Cooper 
34857718be8SEnji Cooper 	ATF_REQUIRE(munlock(buf, page) == 0);
34957718be8SEnji Cooper 	free(buf);
35057718be8SEnji Cooper }
35157718be8SEnji Cooper 
3528e62f841SEnji Cooper #ifdef __FreeBSD__
3538e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_nested, tc)
3548e62f841SEnji Cooper {
3558e62f841SEnji Cooper 
3568e62f841SEnji Cooper 	restore_vm_max_wired();
3578e62f841SEnji Cooper }
3588e62f841SEnji Cooper #endif
3598e62f841SEnji Cooper 
36076f9d275SAlan Somers #ifdef __FreeBSD__
36176f9d275SAlan Somers ATF_TC_WITH_CLEANUP(mlock_unaligned);
36276f9d275SAlan Somers #else
36376f9d275SAlan Somers ATF_TC(mlock_unaligned);
36476f9d275SAlan Somers #endif
36576f9d275SAlan Somers ATF_TC_HEAD(mlock_unaligned, tc)
36676f9d275SAlan Somers {
36776f9d275SAlan Somers 	atf_tc_set_md_var(tc, "descr",
36876f9d275SAlan Somers 	    "Test that mlock(2) can lock page-unaligned memory");
36976f9d275SAlan Somers #ifdef __FreeBSD__
37076f9d275SAlan Somers 	atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
37176f9d275SAlan Somers 	atf_tc_set_md_var(tc, "require.user", "root");
37276f9d275SAlan Somers #endif
37376f9d275SAlan Somers }
37476f9d275SAlan Somers 
37576f9d275SAlan Somers ATF_TC_BODY(mlock_unaligned, tc)
37676f9d275SAlan Somers {
37776f9d275SAlan Somers 	void *buf, *addr;
37876f9d275SAlan Somers 
37976f9d275SAlan Somers #ifdef __FreeBSD__
38076f9d275SAlan Somers 	/* Set max_wired really really high to avoid EAGAIN */
38176f9d275SAlan Somers 	set_vm_max_wired(INT_MAX);
38276f9d275SAlan Somers #endif
38376f9d275SAlan Somers 
38476f9d275SAlan Somers 	buf = malloc(page);
38576f9d275SAlan Somers 	ATF_REQUIRE(buf != NULL);
38676f9d275SAlan Somers 
38776f9d275SAlan Somers 	if ((uintptr_t)buf & ((uintptr_t)page - 1))
38876f9d275SAlan Somers 		addr = buf;
38976f9d275SAlan Somers 	else
39076f9d275SAlan Somers 		addr = (void *)(((uintptr_t)buf) + page/3);
39176f9d275SAlan Somers 
39276f9d275SAlan Somers 	ATF_REQUIRE_EQ(mlock(addr, page/5), 0);
39376f9d275SAlan Somers 	ATF_REQUIRE_EQ(munlock(addr, page/5), 0);
39476f9d275SAlan Somers 
39576f9d275SAlan Somers 	(void)free(buf);
39676f9d275SAlan Somers }
39776f9d275SAlan Somers 
39876f9d275SAlan Somers #ifdef __FreeBSD__
39976f9d275SAlan Somers ATF_TC_CLEANUP(mlock_unaligned, tc)
40076f9d275SAlan Somers {
40176f9d275SAlan Somers 
40276f9d275SAlan Somers 	restore_vm_max_wired();
40376f9d275SAlan Somers }
40476f9d275SAlan Somers #endif
40576f9d275SAlan Somers 
40676f9d275SAlan Somers ATF_TC(munlock_unlocked);
40776f9d275SAlan Somers ATF_TC_HEAD(munlock_unlocked, tc)
40876f9d275SAlan Somers {
40976f9d275SAlan Somers 	atf_tc_set_md_var(tc, "descr",
41076f9d275SAlan Somers #ifdef __FreeBSD__
41176f9d275SAlan Somers 	    "munlock(2) accepts unlocked memory");
41276f9d275SAlan Somers #else
41376f9d275SAlan Somers 	    "munlock(2) of unlocked memory is an error");
41476f9d275SAlan Somers #endif
41576f9d275SAlan Somers 	atf_tc_set_md_var(tc, "require.user", "root");
41676f9d275SAlan Somers }
41776f9d275SAlan Somers 
41876f9d275SAlan Somers ATF_TC_BODY(munlock_unlocked, tc)
41976f9d275SAlan Somers {
42076f9d275SAlan Somers 	void *buf;
42176f9d275SAlan Somers 
42276f9d275SAlan Somers 	buf = malloc(page);
42376f9d275SAlan Somers 	ATF_REQUIRE(buf != NULL);
42476f9d275SAlan Somers 
42576f9d275SAlan Somers #ifdef __FreeBSD__
42676f9d275SAlan Somers 	ATF_REQUIRE_EQ(munlock(buf, page), 0);
42776f9d275SAlan Somers #else
42876f9d275SAlan Somers 	errno = 0;
42976f9d275SAlan Somers 	ATF_REQUIRE_ERRNO(ENOMEM, munlock(buf, page) == -1);
43076f9d275SAlan Somers #endif
43176f9d275SAlan Somers 	(void)free(buf);
43276f9d275SAlan Somers }
43376f9d275SAlan Somers 
43457718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
43557718be8SEnji Cooper {
43657718be8SEnji Cooper 
43757718be8SEnji Cooper 	page = sysconf(_SC_PAGESIZE);
43857718be8SEnji Cooper 	ATF_REQUIRE(page >= 0);
43957718be8SEnji Cooper 
44057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mlock_clip);
44157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mlock_err);
44257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mlock_limits);
44357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mlock_mmap);
44457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mlock_nested);
44576f9d275SAlan Somers 	ATF_TP_ADD_TC(tp, mlock_unaligned);
44676f9d275SAlan Somers 	ATF_TP_ADD_TC(tp, munlock_unlocked);
44757718be8SEnji Cooper 
44857718be8SEnji Cooper 	return atf_no_error();
44957718be8SEnji Cooper }
450