xref: /freebsd/tools/regression/posixsem/posixsem.c (revision 6bfca4dcab07dad45a805879d954876b353c0810)
16bc1e9cdSJohn Baldwin /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
46bc1e9cdSJohn Baldwin  * Copyright (c) 2008 Yahoo!, Inc.
56bc1e9cdSJohn Baldwin  * All rights reserved.
66bc1e9cdSJohn Baldwin  * Written by: John Baldwin <jhb@FreeBSD.org>
76bc1e9cdSJohn Baldwin  *
86bc1e9cdSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
96bc1e9cdSJohn Baldwin  * modification, are permitted provided that the following conditions
106bc1e9cdSJohn Baldwin  * are met:
116bc1e9cdSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
126bc1e9cdSJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
136bc1e9cdSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
146bc1e9cdSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
156bc1e9cdSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
166bc1e9cdSJohn Baldwin  * 3. Neither the name of the author nor the names of any co-contributors
176bc1e9cdSJohn Baldwin  *    may be used to endorse or promote products derived from this software
186bc1e9cdSJohn Baldwin  *    without specific prior written permission.
196bc1e9cdSJohn Baldwin  *
206bc1e9cdSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216bc1e9cdSJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226bc1e9cdSJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236bc1e9cdSJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246bc1e9cdSJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256bc1e9cdSJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266bc1e9cdSJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276bc1e9cdSJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286bc1e9cdSJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296bc1e9cdSJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306bc1e9cdSJohn Baldwin  * SUCH DAMAGE.
316bc1e9cdSJohn Baldwin  */
326bc1e9cdSJohn Baldwin 
336bc1e9cdSJohn Baldwin #include <sys/param.h>
346bc1e9cdSJohn Baldwin #include <sys/queue.h>
356bc1e9cdSJohn Baldwin #include <sys/_semaphore.h>
366bc1e9cdSJohn Baldwin #include <sys/sysctl.h>
376bc1e9cdSJohn Baldwin #include <sys/time.h>
386bc1e9cdSJohn Baldwin #include <sys/user.h>
396bc1e9cdSJohn Baldwin #include <sys/wait.h>
406bc1e9cdSJohn Baldwin 
416bc1e9cdSJohn Baldwin #include <errno.h>
426bc1e9cdSJohn Baldwin #include <fcntl.h>
436bc1e9cdSJohn Baldwin #include <kvm.h>
446bc1e9cdSJohn Baldwin #include <limits.h>
456bc1e9cdSJohn Baldwin #include <semaphore.h>
466bc1e9cdSJohn Baldwin #include <signal.h>
476bc1e9cdSJohn Baldwin #include <stdio.h>
486bc1e9cdSJohn Baldwin #include <stdlib.h>
496bc1e9cdSJohn Baldwin #include <string.h>
506bc1e9cdSJohn Baldwin #include <time.h>
516bc1e9cdSJohn Baldwin #include <unistd.h>
526bc1e9cdSJohn Baldwin 
536bc1e9cdSJohn Baldwin #include "test.h"
546bc1e9cdSJohn Baldwin 
556bc1e9cdSJohn Baldwin #define	TEST_PATH	"/tmp/posixsem_regression_test"
566bc1e9cdSJohn Baldwin 
576bc1e9cdSJohn Baldwin #define	ELAPSED(elapsed, limit)		(abs((elapsed) - (limit)) < 100)
586bc1e9cdSJohn Baldwin 
596bc1e9cdSJohn Baldwin /* Macros for passing child status to parent over a pipe. */
606bc1e9cdSJohn Baldwin #define	CSTAT(class, error)		((class) << 16 | (error))
616bc1e9cdSJohn Baldwin #define	CSTAT_CLASS(stat)		((stat) >> 16)
626bc1e9cdSJohn Baldwin #define	CSTAT_ERROR(stat)		((stat) & 0xffff)
636bc1e9cdSJohn Baldwin 
646bc1e9cdSJohn Baldwin /*
656bc1e9cdSJohn Baldwin  * Helper routine for tests that use a child process.  This routine
666bc1e9cdSJohn Baldwin  * creates a pipe and forks a child process.  The child process runs
676bc1e9cdSJohn Baldwin  * the 'func' routine which returns a status integer.  The status
686bc1e9cdSJohn Baldwin  * integer gets written over the pipe to the parent and returned in
696bc1e9cdSJohn Baldwin  * '*stat'.  If there is an error in pipe(), fork(), or wait() this
706bc1e9cdSJohn Baldwin  * returns -1 and fails the test.
716bc1e9cdSJohn Baldwin  */
726bc1e9cdSJohn Baldwin static int
child_worker(int (* func)(void * arg),void * arg,int * stat)736bc1e9cdSJohn Baldwin child_worker(int (*func)(void *arg), void *arg, int *stat)
746bc1e9cdSJohn Baldwin {
756bc1e9cdSJohn Baldwin 	pid_t pid;
766bc1e9cdSJohn Baldwin 	int pfd[2], cstat;
776bc1e9cdSJohn Baldwin 
786bc1e9cdSJohn Baldwin 	if (pipe(pfd) < 0) {
796bc1e9cdSJohn Baldwin 		fail_errno("pipe");
806bc1e9cdSJohn Baldwin 		return (-1);
816bc1e9cdSJohn Baldwin 	}
826bc1e9cdSJohn Baldwin 
836bc1e9cdSJohn Baldwin 	pid = fork();
846bc1e9cdSJohn Baldwin 	switch (pid) {
856bc1e9cdSJohn Baldwin 	case -1:
866bc1e9cdSJohn Baldwin 		/* Error. */
876bc1e9cdSJohn Baldwin 		fail_errno("fork");
886bc1e9cdSJohn Baldwin 		close(pfd[0]);
896bc1e9cdSJohn Baldwin 		close(pfd[1]);
906bc1e9cdSJohn Baldwin 		return (-1);
916bc1e9cdSJohn Baldwin 	case 0:
926bc1e9cdSJohn Baldwin 		/* Child. */
936bc1e9cdSJohn Baldwin 		cstat = func(arg);
946bc1e9cdSJohn Baldwin 		write(pfd[1], &cstat, sizeof(cstat));
956bc1e9cdSJohn Baldwin 		exit(0);
966bc1e9cdSJohn Baldwin 	}
976bc1e9cdSJohn Baldwin 
986bc1e9cdSJohn Baldwin 	if (read(pfd[0], stat, sizeof(*stat)) < 0) {
996bc1e9cdSJohn Baldwin 		fail_errno("read(pipe)");
1006bc1e9cdSJohn Baldwin 		close(pfd[0]);
1016bc1e9cdSJohn Baldwin 		close(pfd[1]);
1026bc1e9cdSJohn Baldwin 		return (-1);
1036bc1e9cdSJohn Baldwin 	}
1046bc1e9cdSJohn Baldwin 	if (waitpid(pid, NULL, 0) < 0) {
1056bc1e9cdSJohn Baldwin 		fail_errno("wait");
1066bc1e9cdSJohn Baldwin 		close(pfd[0]);
1076bc1e9cdSJohn Baldwin 		close(pfd[1]);
1086bc1e9cdSJohn Baldwin 		return (-1);
1096bc1e9cdSJohn Baldwin 	}
1106bc1e9cdSJohn Baldwin 	close(pfd[0]);
1116bc1e9cdSJohn Baldwin 	close(pfd[1]);
1126bc1e9cdSJohn Baldwin 	return (0);
1136bc1e9cdSJohn Baldwin }
1146bc1e9cdSJohn Baldwin 
1156bc1e9cdSJohn Baldwin /*
1166bc1e9cdSJohn Baldwin  * Attempt a ksem_open() that should fail with an expected error of
1176bc1e9cdSJohn Baldwin  * 'error'.
1186bc1e9cdSJohn Baldwin  */
1196bc1e9cdSJohn Baldwin static void
ksem_open_should_fail(const char * path,int flags,mode_t mode,unsigned int value,int error)1206bc1e9cdSJohn Baldwin ksem_open_should_fail(const char *path, int flags, mode_t mode, unsigned int
1216bc1e9cdSJohn Baldwin     value, int error)
1226bc1e9cdSJohn Baldwin {
1236bc1e9cdSJohn Baldwin 	semid_t id;
1246bc1e9cdSJohn Baldwin 
1256bc1e9cdSJohn Baldwin 	if (ksem_open(&id, path, flags, mode, value) >= 0) {
1266bc1e9cdSJohn Baldwin 		fail_err("ksem_open() didn't fail");
1276bc1e9cdSJohn Baldwin 		ksem_close(id);
1286bc1e9cdSJohn Baldwin 		return;
1296bc1e9cdSJohn Baldwin 	}
1306bc1e9cdSJohn Baldwin 	if (errno != error) {
1316bc1e9cdSJohn Baldwin 		fail_errno("ksem_open");
1326bc1e9cdSJohn Baldwin 		return;
1336bc1e9cdSJohn Baldwin 	}
1346bc1e9cdSJohn Baldwin 	pass();
1356bc1e9cdSJohn Baldwin }
1366bc1e9cdSJohn Baldwin 
1376bc1e9cdSJohn Baldwin /*
1386bc1e9cdSJohn Baldwin  * Attempt a ksem_unlink() that should fail with an expected error of
1396bc1e9cdSJohn Baldwin  * 'error'.
1406bc1e9cdSJohn Baldwin  */
1416bc1e9cdSJohn Baldwin static void
ksem_unlink_should_fail(const char * path,int error)1426bc1e9cdSJohn Baldwin ksem_unlink_should_fail(const char *path, int error)
1436bc1e9cdSJohn Baldwin {
1446bc1e9cdSJohn Baldwin 
1456bc1e9cdSJohn Baldwin 	if (ksem_unlink(path) >= 0) {
1466bc1e9cdSJohn Baldwin 		fail_err("ksem_unlink() didn't fail");
1476bc1e9cdSJohn Baldwin 		return;
1486bc1e9cdSJohn Baldwin 	}
1496bc1e9cdSJohn Baldwin 	if (errno != error) {
1506bc1e9cdSJohn Baldwin 		fail_errno("ksem_unlink");
1516bc1e9cdSJohn Baldwin 		return;
1526bc1e9cdSJohn Baldwin 	}
1536bc1e9cdSJohn Baldwin 	pass();
1546bc1e9cdSJohn Baldwin }
1556bc1e9cdSJohn Baldwin 
1566bc1e9cdSJohn Baldwin /*
1576bc1e9cdSJohn Baldwin  * Attempt a ksem_close() that should fail with an expected error of
1586bc1e9cdSJohn Baldwin  * 'error'.
1596bc1e9cdSJohn Baldwin  */
1606bc1e9cdSJohn Baldwin static void
ksem_close_should_fail(semid_t id,int error)1616bc1e9cdSJohn Baldwin ksem_close_should_fail(semid_t id, int error)
1626bc1e9cdSJohn Baldwin {
1636bc1e9cdSJohn Baldwin 
1646bc1e9cdSJohn Baldwin 	if (ksem_close(id) >= 0) {
1656bc1e9cdSJohn Baldwin 		fail_err("ksem_close() didn't fail");
1666bc1e9cdSJohn Baldwin 		return;
1676bc1e9cdSJohn Baldwin 	}
1686bc1e9cdSJohn Baldwin 	if (errno != error) {
1696bc1e9cdSJohn Baldwin 		fail_errno("ksem_close");
1706bc1e9cdSJohn Baldwin 		return;
1716bc1e9cdSJohn Baldwin 	}
1726bc1e9cdSJohn Baldwin 	pass();
1736bc1e9cdSJohn Baldwin }
1746bc1e9cdSJohn Baldwin 
1756bc1e9cdSJohn Baldwin /*
1766bc1e9cdSJohn Baldwin  * Attempt a ksem_init() that should fail with an expected error of
1776bc1e9cdSJohn Baldwin  * 'error'.
1786bc1e9cdSJohn Baldwin  */
1796bc1e9cdSJohn Baldwin static void
ksem_init_should_fail(unsigned int value,int error)1806bc1e9cdSJohn Baldwin ksem_init_should_fail(unsigned int value, int error)
1816bc1e9cdSJohn Baldwin {
1826bc1e9cdSJohn Baldwin 	semid_t id;
1836bc1e9cdSJohn Baldwin 
1846bc1e9cdSJohn Baldwin 	if (ksem_init(&id, value) >= 0) {
1856bc1e9cdSJohn Baldwin 		fail_err("ksem_init() didn't fail");
1866bc1e9cdSJohn Baldwin 		ksem_destroy(id);
1876bc1e9cdSJohn Baldwin 		return;
1886bc1e9cdSJohn Baldwin 	}
1896bc1e9cdSJohn Baldwin 	if (errno != error) {
1906bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
1916bc1e9cdSJohn Baldwin 		return;
1926bc1e9cdSJohn Baldwin 	}
1936bc1e9cdSJohn Baldwin 	pass();
1946bc1e9cdSJohn Baldwin }
1956bc1e9cdSJohn Baldwin 
1966bc1e9cdSJohn Baldwin /*
1976bc1e9cdSJohn Baldwin  * Attempt a ksem_destroy() that should fail with an expected error of
1986bc1e9cdSJohn Baldwin  * 'error'.
1996bc1e9cdSJohn Baldwin  */
2006bc1e9cdSJohn Baldwin static void
ksem_destroy_should_fail(semid_t id,int error)2016bc1e9cdSJohn Baldwin ksem_destroy_should_fail(semid_t id, int error)
2026bc1e9cdSJohn Baldwin {
2036bc1e9cdSJohn Baldwin 
2046bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) >= 0) {
2056bc1e9cdSJohn Baldwin 		fail_err("ksem_destroy() didn't fail");
2066bc1e9cdSJohn Baldwin 		return;
2076bc1e9cdSJohn Baldwin 	}
2086bc1e9cdSJohn Baldwin 	if (errno != error) {
2096bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
2106bc1e9cdSJohn Baldwin 		return;
2116bc1e9cdSJohn Baldwin 	}
2126bc1e9cdSJohn Baldwin 	pass();
2136bc1e9cdSJohn Baldwin }
2146bc1e9cdSJohn Baldwin 
2156bc1e9cdSJohn Baldwin /*
2166bc1e9cdSJohn Baldwin  * Attempt a ksem_post() that should fail with an expected error of
2176bc1e9cdSJohn Baldwin  * 'error'.
2186bc1e9cdSJohn Baldwin  */
2196bc1e9cdSJohn Baldwin static void
ksem_post_should_fail(semid_t id,int error)2206bc1e9cdSJohn Baldwin ksem_post_should_fail(semid_t id, int error)
2216bc1e9cdSJohn Baldwin {
2226bc1e9cdSJohn Baldwin 
2236bc1e9cdSJohn Baldwin 	if (ksem_post(id) >= 0) {
2246bc1e9cdSJohn Baldwin 		fail_err("ksem_post() didn't fail");
2256bc1e9cdSJohn Baldwin 		return;
2266bc1e9cdSJohn Baldwin 	}
2276bc1e9cdSJohn Baldwin 	if (errno != error) {
2286bc1e9cdSJohn Baldwin 		fail_errno("ksem_post");
2296bc1e9cdSJohn Baldwin 		return;
2306bc1e9cdSJohn Baldwin 	}
2316bc1e9cdSJohn Baldwin 	pass();
2326bc1e9cdSJohn Baldwin }
2336bc1e9cdSJohn Baldwin 
2346bc1e9cdSJohn Baldwin static void
open_after_unlink(void)2356bc1e9cdSJohn Baldwin open_after_unlink(void)
2366bc1e9cdSJohn Baldwin {
2376bc1e9cdSJohn Baldwin 	semid_t id;
2386bc1e9cdSJohn Baldwin 
2396bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT, 0777, 1) < 0) {
2406bc1e9cdSJohn Baldwin 		fail_errno("ksem_open(1)");
2416bc1e9cdSJohn Baldwin 		return;
2426bc1e9cdSJohn Baldwin 	}
2436bc1e9cdSJohn Baldwin 	ksem_close(id);
2446bc1e9cdSJohn Baldwin 
2456bc1e9cdSJohn Baldwin 	if (ksem_unlink(TEST_PATH) < 0) {
2466bc1e9cdSJohn Baldwin 		fail_errno("ksem_unlink");
2476bc1e9cdSJohn Baldwin 		return;
2486bc1e9cdSJohn Baldwin 	}
2496bc1e9cdSJohn Baldwin 
2506bc1e9cdSJohn Baldwin 	ksem_open_should_fail(TEST_PATH, O_RDONLY, 0777, 1, ENOENT);
2516bc1e9cdSJohn Baldwin }
2526bc1e9cdSJohn Baldwin TEST(open_after_unlink, "open after unlink");
2536bc1e9cdSJohn Baldwin 
2546bc1e9cdSJohn Baldwin static void
open_invalid_path(void)2556bc1e9cdSJohn Baldwin open_invalid_path(void)
2566bc1e9cdSJohn Baldwin {
2576bc1e9cdSJohn Baldwin 
2586bc1e9cdSJohn Baldwin 	ksem_open_should_fail("blah", 0, 0777, 1, EINVAL);
2596bc1e9cdSJohn Baldwin }
2606bc1e9cdSJohn Baldwin TEST(open_invalid_path, "open invalid path");
2616bc1e9cdSJohn Baldwin 
2626bc1e9cdSJohn Baldwin static void
open_extra_flags(void)2636bc1e9cdSJohn Baldwin open_extra_flags(void)
2646bc1e9cdSJohn Baldwin {
2656bc1e9cdSJohn Baldwin 
2666bc1e9cdSJohn Baldwin 	ksem_open_should_fail(TEST_PATH, O_RDONLY | O_DIRECT, 0777, 1, EINVAL);
2676bc1e9cdSJohn Baldwin }
2686bc1e9cdSJohn Baldwin TEST(open_extra_flags, "open with extra flags");
2696bc1e9cdSJohn Baldwin 
2706bc1e9cdSJohn Baldwin static void
open_bad_value(void)2716bc1e9cdSJohn Baldwin open_bad_value(void)
2726bc1e9cdSJohn Baldwin {
2736bc1e9cdSJohn Baldwin 
2746bc1e9cdSJohn Baldwin 	(void)ksem_unlink(TEST_PATH);
2756bc1e9cdSJohn Baldwin 
2766bc1e9cdSJohn Baldwin 	ksem_open_should_fail(TEST_PATH, O_CREAT, 0777, UINT_MAX, EINVAL);
2776bc1e9cdSJohn Baldwin }
2786bc1e9cdSJohn Baldwin TEST(open_bad_value, "open with invalid initial value");
2796bc1e9cdSJohn Baldwin 
2806bc1e9cdSJohn Baldwin static void
open_bad_path_pointer(void)2816bc1e9cdSJohn Baldwin open_bad_path_pointer(void)
2826bc1e9cdSJohn Baldwin {
2836bc1e9cdSJohn Baldwin 
2846bc1e9cdSJohn Baldwin 	ksem_open_should_fail((char *)1024, O_RDONLY, 0777, 1, EFAULT);
2856bc1e9cdSJohn Baldwin }
2866bc1e9cdSJohn Baldwin TEST(open_bad_path_pointer, "open bad path pointer");
2876bc1e9cdSJohn Baldwin 
2886bc1e9cdSJohn Baldwin static void
open_path_too_long(void)2896bc1e9cdSJohn Baldwin open_path_too_long(void)
2906bc1e9cdSJohn Baldwin {
2916bc1e9cdSJohn Baldwin 	char *page;
2926bc1e9cdSJohn Baldwin 
2936bc1e9cdSJohn Baldwin 	page = malloc(MAXPATHLEN + 1);
2946bc1e9cdSJohn Baldwin 	memset(page, 'a', MAXPATHLEN);
2956bc1e9cdSJohn Baldwin 	page[MAXPATHLEN] = '\0';
2966bc1e9cdSJohn Baldwin 	ksem_open_should_fail(page, O_RDONLY, 0777, 1, ENAMETOOLONG);
2976bc1e9cdSJohn Baldwin 	free(page);
2986bc1e9cdSJohn Baldwin }
2996bc1e9cdSJohn Baldwin TEST(open_path_too_long, "open pathname too long");
3006bc1e9cdSJohn Baldwin 
3016bc1e9cdSJohn Baldwin static void
open_nonexisting_semaphore(void)3026bc1e9cdSJohn Baldwin open_nonexisting_semaphore(void)
3036bc1e9cdSJohn Baldwin {
3046bc1e9cdSJohn Baldwin 
3056bc1e9cdSJohn Baldwin 	ksem_open_should_fail("/notreallythere", 0, 0777, 1, ENOENT);
3066bc1e9cdSJohn Baldwin }
3076bc1e9cdSJohn Baldwin TEST(open_nonexisting_semaphore, "open nonexistent semaphore");
3086bc1e9cdSJohn Baldwin 
3096bc1e9cdSJohn Baldwin static void
exclusive_create_existing_semaphore(void)3106bc1e9cdSJohn Baldwin exclusive_create_existing_semaphore(void)
3116bc1e9cdSJohn Baldwin {
3126bc1e9cdSJohn Baldwin 	semid_t id;
3136bc1e9cdSJohn Baldwin 
3146bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT, 0777, 1) < 0) {
3156bc1e9cdSJohn Baldwin 		fail_errno("ksem_open(O_CREAT)");
3166bc1e9cdSJohn Baldwin 		return;
3176bc1e9cdSJohn Baldwin 	}
3186bc1e9cdSJohn Baldwin 	ksem_close(id);
3196bc1e9cdSJohn Baldwin 
3206bc1e9cdSJohn Baldwin 	ksem_open_should_fail(TEST_PATH, O_CREAT | O_EXCL, 0777, 1, EEXIST);
3216bc1e9cdSJohn Baldwin 
3226bc1e9cdSJohn Baldwin 	ksem_unlink(TEST_PATH);
3236bc1e9cdSJohn Baldwin }
3246bc1e9cdSJohn Baldwin TEST(exclusive_create_existing_semaphore, "O_EXCL of existing semaphore");
3256bc1e9cdSJohn Baldwin 
3266bc1e9cdSJohn Baldwin static void
init_bad_value(void)3276bc1e9cdSJohn Baldwin init_bad_value(void)
3286bc1e9cdSJohn Baldwin {
3296bc1e9cdSJohn Baldwin 
3306bc1e9cdSJohn Baldwin 	ksem_init_should_fail(UINT_MAX, EINVAL);
3316bc1e9cdSJohn Baldwin }
3326bc1e9cdSJohn Baldwin TEST(init_bad_value, "init with invalid initial value");
3336bc1e9cdSJohn Baldwin 
3346bc1e9cdSJohn Baldwin static void
unlink_bad_path_pointer(void)3356bc1e9cdSJohn Baldwin unlink_bad_path_pointer(void)
3366bc1e9cdSJohn Baldwin {
3376bc1e9cdSJohn Baldwin 
3386bc1e9cdSJohn Baldwin 	ksem_unlink_should_fail((char *)1024, EFAULT);
3396bc1e9cdSJohn Baldwin }
3406bc1e9cdSJohn Baldwin TEST(unlink_bad_path_pointer, "unlink bad path pointer");
3416bc1e9cdSJohn Baldwin 
3426bc1e9cdSJohn Baldwin static void
unlink_path_too_long(void)3436bc1e9cdSJohn Baldwin unlink_path_too_long(void)
3446bc1e9cdSJohn Baldwin {
3456bc1e9cdSJohn Baldwin 	char *page;
3466bc1e9cdSJohn Baldwin 
3476bc1e9cdSJohn Baldwin 	page = malloc(MAXPATHLEN + 1);
3486bc1e9cdSJohn Baldwin 	memset(page, 'a', MAXPATHLEN);
3496bc1e9cdSJohn Baldwin 	page[MAXPATHLEN] = '\0';
3506bc1e9cdSJohn Baldwin 	ksem_unlink_should_fail(page, ENAMETOOLONG);
3516bc1e9cdSJohn Baldwin 	free(page);
3526bc1e9cdSJohn Baldwin }
3536bc1e9cdSJohn Baldwin TEST(unlink_path_too_long, "unlink pathname too long");
3546bc1e9cdSJohn Baldwin 
3556bc1e9cdSJohn Baldwin static void
destroy_named_semaphore(void)3566bc1e9cdSJohn Baldwin destroy_named_semaphore(void)
3576bc1e9cdSJohn Baldwin {
3586bc1e9cdSJohn Baldwin 	semid_t id;
3596bc1e9cdSJohn Baldwin 
3606bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT, 0777, 1) < 0) {
3616bc1e9cdSJohn Baldwin 		fail_errno("ksem_open(O_CREAT)");
3626bc1e9cdSJohn Baldwin 		return;
3636bc1e9cdSJohn Baldwin 	}
3646bc1e9cdSJohn Baldwin 
3656bc1e9cdSJohn Baldwin 	ksem_destroy_should_fail(id, EINVAL);
3666bc1e9cdSJohn Baldwin 
3676bc1e9cdSJohn Baldwin 	ksem_close(id);
3686bc1e9cdSJohn Baldwin 	ksem_unlink(TEST_PATH);
3696bc1e9cdSJohn Baldwin }
3706bc1e9cdSJohn Baldwin TEST(destroy_named_semaphore, "destroy named semaphore");
3716bc1e9cdSJohn Baldwin 
3726bc1e9cdSJohn Baldwin static void
close_unnamed_semaphore(void)3736bc1e9cdSJohn Baldwin close_unnamed_semaphore(void)
3746bc1e9cdSJohn Baldwin {
3756bc1e9cdSJohn Baldwin 	semid_t id;
3766bc1e9cdSJohn Baldwin 
3776bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
3786bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
3796bc1e9cdSJohn Baldwin 		return;
3806bc1e9cdSJohn Baldwin 	}
3816bc1e9cdSJohn Baldwin 
3826bc1e9cdSJohn Baldwin 	ksem_close_should_fail(id, EINVAL);
3836bc1e9cdSJohn Baldwin 
3846bc1e9cdSJohn Baldwin 	ksem_destroy(id);
3856bc1e9cdSJohn Baldwin }
3866bc1e9cdSJohn Baldwin TEST(close_unnamed_semaphore, "close unnamed semaphore");
3876bc1e9cdSJohn Baldwin 
3886bc1e9cdSJohn Baldwin static void
destroy_invalid_fd(void)3896bc1e9cdSJohn Baldwin destroy_invalid_fd(void)
3906bc1e9cdSJohn Baldwin {
3916bc1e9cdSJohn Baldwin 
3926bc1e9cdSJohn Baldwin 	ksem_destroy_should_fail(STDERR_FILENO, EINVAL);
3936bc1e9cdSJohn Baldwin }
3946bc1e9cdSJohn Baldwin TEST(destroy_invalid_fd, "destroy non-semaphore file descriptor");
3956bc1e9cdSJohn Baldwin 
3966bc1e9cdSJohn Baldwin static void
close_invalid_fd(void)3976bc1e9cdSJohn Baldwin close_invalid_fd(void)
3986bc1e9cdSJohn Baldwin {
3996bc1e9cdSJohn Baldwin 
4006bc1e9cdSJohn Baldwin 	ksem_close_should_fail(STDERR_FILENO, EINVAL);
4016bc1e9cdSJohn Baldwin }
4026bc1e9cdSJohn Baldwin TEST(close_invalid_fd, "close non-semaphore file descriptor");
4036bc1e9cdSJohn Baldwin 
4046bc1e9cdSJohn Baldwin static void
create_unnamed_semaphore(void)4056bc1e9cdSJohn Baldwin create_unnamed_semaphore(void)
4066bc1e9cdSJohn Baldwin {
4076bc1e9cdSJohn Baldwin 	semid_t id;
4086bc1e9cdSJohn Baldwin 
4096bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
4106bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
4116bc1e9cdSJohn Baldwin 		return;
4126bc1e9cdSJohn Baldwin 	}
4136bc1e9cdSJohn Baldwin 
4146bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
4156bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
4166bc1e9cdSJohn Baldwin 		return;
4176bc1e9cdSJohn Baldwin 	}
4186bc1e9cdSJohn Baldwin 	pass();
4196bc1e9cdSJohn Baldwin }
4206bc1e9cdSJohn Baldwin TEST(create_unnamed_semaphore, "create unnamed semaphore");
4216bc1e9cdSJohn Baldwin 
4226bc1e9cdSJohn Baldwin static void
open_named_semaphore(void)4236bc1e9cdSJohn Baldwin open_named_semaphore(void)
4246bc1e9cdSJohn Baldwin {
4256bc1e9cdSJohn Baldwin 	semid_t id;
4266bc1e9cdSJohn Baldwin 
4276bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT, 0777, 1) < 0) {
4286bc1e9cdSJohn Baldwin 		fail_errno("ksem_open(O_CREAT)");
4296bc1e9cdSJohn Baldwin 		return;
4306bc1e9cdSJohn Baldwin 	}
4316bc1e9cdSJohn Baldwin 
4326bc1e9cdSJohn Baldwin 	if (ksem_close(id) < 0) {
4336bc1e9cdSJohn Baldwin 		fail_errno("ksem_close");
4346bc1e9cdSJohn Baldwin 		return;
4356bc1e9cdSJohn Baldwin 	}
4366bc1e9cdSJohn Baldwin 
4376bc1e9cdSJohn Baldwin 	if (ksem_unlink(TEST_PATH) < 0) {
4386bc1e9cdSJohn Baldwin 		fail_errno("ksem_unlink");
4396bc1e9cdSJohn Baldwin 		return;
4406bc1e9cdSJohn Baldwin 	}
4416bc1e9cdSJohn Baldwin 	pass();
4426bc1e9cdSJohn Baldwin }
4436bc1e9cdSJohn Baldwin TEST(open_named_semaphore, "create named semaphore");
4446bc1e9cdSJohn Baldwin 
4456bc1e9cdSJohn Baldwin static void
getvalue_invalid_semaphore(void)4466bc1e9cdSJohn Baldwin getvalue_invalid_semaphore(void)
4476bc1e9cdSJohn Baldwin {
4486bc1e9cdSJohn Baldwin 	int val;
4496bc1e9cdSJohn Baldwin 
4506bc1e9cdSJohn Baldwin 	if (ksem_getvalue(STDERR_FILENO, &val) >= 0) {
4516bc1e9cdSJohn Baldwin 		fail_err("ksem_getvalue() didn't fail");
4526bc1e9cdSJohn Baldwin 		return;
4536bc1e9cdSJohn Baldwin 	}
4546bc1e9cdSJohn Baldwin 	if (errno != EINVAL) {
4556bc1e9cdSJohn Baldwin 		fail_errno("ksem_getvalue");
4566bc1e9cdSJohn Baldwin 		return;
4576bc1e9cdSJohn Baldwin 	}
4586bc1e9cdSJohn Baldwin 	pass();
4596bc1e9cdSJohn Baldwin }
4606bc1e9cdSJohn Baldwin TEST(getvalue_invalid_semaphore, "get value of invalid semaphore");
4616bc1e9cdSJohn Baldwin 
4626bc1e9cdSJohn Baldwin static void
post_invalid_semaphore(void)4636bc1e9cdSJohn Baldwin post_invalid_semaphore(void)
4646bc1e9cdSJohn Baldwin {
4656bc1e9cdSJohn Baldwin 
4666bc1e9cdSJohn Baldwin 	ksem_post_should_fail(STDERR_FILENO, EINVAL);
4676bc1e9cdSJohn Baldwin }
4686bc1e9cdSJohn Baldwin TEST(post_invalid_semaphore, "post of invalid semaphore");
4696bc1e9cdSJohn Baldwin 
4706bc1e9cdSJohn Baldwin static void
wait_invalid_semaphore(void)4716bc1e9cdSJohn Baldwin wait_invalid_semaphore(void)
4726bc1e9cdSJohn Baldwin {
4736bc1e9cdSJohn Baldwin 
4746bc1e9cdSJohn Baldwin 	if (ksem_wait(STDERR_FILENO) >= 0) {
4756bc1e9cdSJohn Baldwin 		fail_err("ksem_wait() didn't fail");
4766bc1e9cdSJohn Baldwin 		return;
4776bc1e9cdSJohn Baldwin 	}
4786bc1e9cdSJohn Baldwin 	if (errno != EINVAL) {
4796bc1e9cdSJohn Baldwin 		fail_errno("ksem_wait");
4806bc1e9cdSJohn Baldwin 		return;
4816bc1e9cdSJohn Baldwin 	}
4826bc1e9cdSJohn Baldwin 	pass();
4836bc1e9cdSJohn Baldwin }
4846bc1e9cdSJohn Baldwin TEST(wait_invalid_semaphore, "wait for invalid semaphore");
4856bc1e9cdSJohn Baldwin 
4866bc1e9cdSJohn Baldwin static void
trywait_invalid_semaphore(void)4876bc1e9cdSJohn Baldwin trywait_invalid_semaphore(void)
4886bc1e9cdSJohn Baldwin {
4896bc1e9cdSJohn Baldwin 
4906bc1e9cdSJohn Baldwin 	if (ksem_trywait(STDERR_FILENO) >= 0) {
4916bc1e9cdSJohn Baldwin 		fail_err("ksem_trywait() didn't fail");
4926bc1e9cdSJohn Baldwin 		return;
4936bc1e9cdSJohn Baldwin 	}
4946bc1e9cdSJohn Baldwin 	if (errno != EINVAL) {
4956bc1e9cdSJohn Baldwin 		fail_errno("ksem_trywait");
4966bc1e9cdSJohn Baldwin 		return;
4976bc1e9cdSJohn Baldwin 	}
4986bc1e9cdSJohn Baldwin 	pass();
4996bc1e9cdSJohn Baldwin }
5006bc1e9cdSJohn Baldwin TEST(trywait_invalid_semaphore, "try wait for invalid semaphore");
5016bc1e9cdSJohn Baldwin 
5026bc1e9cdSJohn Baldwin static void
timedwait_invalid_semaphore(void)5036bc1e9cdSJohn Baldwin timedwait_invalid_semaphore(void)
5046bc1e9cdSJohn Baldwin {
5056bc1e9cdSJohn Baldwin 
5066bc1e9cdSJohn Baldwin 	if (ksem_timedwait(STDERR_FILENO, NULL) >= 0) {
5076bc1e9cdSJohn Baldwin 		fail_err("ksem_timedwait() didn't fail");
5086bc1e9cdSJohn Baldwin 		return;
5096bc1e9cdSJohn Baldwin 	}
5106bc1e9cdSJohn Baldwin 	if (errno != EINVAL) {
5116bc1e9cdSJohn Baldwin 		fail_errno("ksem_timedwait");
5126bc1e9cdSJohn Baldwin 		return;
5136bc1e9cdSJohn Baldwin 	}
5146bc1e9cdSJohn Baldwin 	pass();
5156bc1e9cdSJohn Baldwin }
5166bc1e9cdSJohn Baldwin TEST(timedwait_invalid_semaphore, "timed wait for invalid semaphore");
5176bc1e9cdSJohn Baldwin 
5186bc1e9cdSJohn Baldwin static int
checkvalue(semid_t id,int expected)5196bc1e9cdSJohn Baldwin checkvalue(semid_t id, int expected)
5206bc1e9cdSJohn Baldwin {
5216bc1e9cdSJohn Baldwin 	int val;
5226bc1e9cdSJohn Baldwin 
5236bc1e9cdSJohn Baldwin 	if (ksem_getvalue(id, &val) < 0) {
5246bc1e9cdSJohn Baldwin 		fail_errno("ksem_getvalue");
5256bc1e9cdSJohn Baldwin 		return (-1);
5266bc1e9cdSJohn Baldwin 	}
5276bc1e9cdSJohn Baldwin 	if (val != expected) {
5286bc1e9cdSJohn Baldwin 		fail_err("sem value should be %d instead of %d", expected, val);
5296bc1e9cdSJohn Baldwin 		return (-1);
5306bc1e9cdSJohn Baldwin 	}
5316bc1e9cdSJohn Baldwin 	return (0);
5326bc1e9cdSJohn Baldwin }
5336bc1e9cdSJohn Baldwin 
5346bc1e9cdSJohn Baldwin static void
post_test(void)5356bc1e9cdSJohn Baldwin post_test(void)
5366bc1e9cdSJohn Baldwin {
5376bc1e9cdSJohn Baldwin 	semid_t id;
5386bc1e9cdSJohn Baldwin 
5396bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
5406bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
5416bc1e9cdSJohn Baldwin 		return;
5426bc1e9cdSJohn Baldwin 	}
5436bc1e9cdSJohn Baldwin 	if (checkvalue(id, 1) < 0) {
5446bc1e9cdSJohn Baldwin 		ksem_destroy(id);
5456bc1e9cdSJohn Baldwin 		return;
5466bc1e9cdSJohn Baldwin 	}
5476bc1e9cdSJohn Baldwin 	if (ksem_post(id) < 0) {
5486bc1e9cdSJohn Baldwin 		fail_errno("ksem_post");
5496bc1e9cdSJohn Baldwin 		ksem_destroy(id);
5506bc1e9cdSJohn Baldwin 		return;
5516bc1e9cdSJohn Baldwin 	}
5526bc1e9cdSJohn Baldwin 	if (checkvalue(id, 2) < 0) {
5536bc1e9cdSJohn Baldwin 		ksem_destroy(id);
5546bc1e9cdSJohn Baldwin 		return;
5556bc1e9cdSJohn Baldwin 	}
5566bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
5576bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
5586bc1e9cdSJohn Baldwin 		return;
5596bc1e9cdSJohn Baldwin 	}
5606bc1e9cdSJohn Baldwin 	pass();
5616bc1e9cdSJohn Baldwin }
5626bc1e9cdSJohn Baldwin TEST(post_test, "simple post");
5636bc1e9cdSJohn Baldwin 
5646bc1e9cdSJohn Baldwin static void
use_after_unlink_test(void)5656bc1e9cdSJohn Baldwin use_after_unlink_test(void)
5666bc1e9cdSJohn Baldwin {
5676bc1e9cdSJohn Baldwin 	semid_t id;
5686bc1e9cdSJohn Baldwin 
5696bc1e9cdSJohn Baldwin 	/*
5706bc1e9cdSJohn Baldwin 	 * Create named semaphore with value of 1 and then unlink it
5716bc1e9cdSJohn Baldwin 	 * while still retaining the initial reference.
5726bc1e9cdSJohn Baldwin 	 */
5736bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT | O_EXCL, 0777, 1) < 0) {
5746bc1e9cdSJohn Baldwin 		fail_errno("ksem_open(O_CREAT | O_EXCL)");
5756bc1e9cdSJohn Baldwin 		return;
5766bc1e9cdSJohn Baldwin 	}
5776bc1e9cdSJohn Baldwin 	if (ksem_unlink(TEST_PATH) < 0) {
5786bc1e9cdSJohn Baldwin 		fail_errno("ksem_unlink");
5796bc1e9cdSJohn Baldwin 		ksem_close(id);
5806bc1e9cdSJohn Baldwin 		return;
5816bc1e9cdSJohn Baldwin 	}
5826bc1e9cdSJohn Baldwin 	if (checkvalue(id, 1) < 0) {
5836bc1e9cdSJohn Baldwin 		ksem_close(id);
5846bc1e9cdSJohn Baldwin 		return;
5856bc1e9cdSJohn Baldwin 	}
5866bc1e9cdSJohn Baldwin 
5876bc1e9cdSJohn Baldwin 	/* Post the semaphore to set its value to 2. */
5886bc1e9cdSJohn Baldwin 	if (ksem_post(id) < 0) {
5896bc1e9cdSJohn Baldwin 		fail_errno("ksem_post");
5906bc1e9cdSJohn Baldwin 		ksem_close(id);
5916bc1e9cdSJohn Baldwin 		return;
5926bc1e9cdSJohn Baldwin 	}
5936bc1e9cdSJohn Baldwin 	if (checkvalue(id, 2) < 0) {
5946bc1e9cdSJohn Baldwin 		ksem_close(id);
5956bc1e9cdSJohn Baldwin 		return;
5966bc1e9cdSJohn Baldwin 	}
5976bc1e9cdSJohn Baldwin 
5986bc1e9cdSJohn Baldwin 	/* Wait on the semaphore which should set its value to 1. */
5996bc1e9cdSJohn Baldwin 	if (ksem_wait(id) < 0) {
6006bc1e9cdSJohn Baldwin 		fail_errno("ksem_wait");
6016bc1e9cdSJohn Baldwin 		ksem_close(id);
6026bc1e9cdSJohn Baldwin 		return;
6036bc1e9cdSJohn Baldwin 	}
6046bc1e9cdSJohn Baldwin 	if (checkvalue(id, 1) < 0) {
6056bc1e9cdSJohn Baldwin 		ksem_close(id);
6066bc1e9cdSJohn Baldwin 		return;
6076bc1e9cdSJohn Baldwin 	}
6086bc1e9cdSJohn Baldwin 
6096bc1e9cdSJohn Baldwin 	if (ksem_close(id) < 0) {
6106bc1e9cdSJohn Baldwin 		fail_errno("ksem_close");
6116bc1e9cdSJohn Baldwin 		return;
6126bc1e9cdSJohn Baldwin 	}
6136bc1e9cdSJohn Baldwin 	pass();
6146bc1e9cdSJohn Baldwin }
6156bc1e9cdSJohn Baldwin TEST(use_after_unlink_test, "use named semaphore after unlink");
6166bc1e9cdSJohn Baldwin 
6176bc1e9cdSJohn Baldwin static void
unlocked_trywait(void)6186bc1e9cdSJohn Baldwin unlocked_trywait(void)
6196bc1e9cdSJohn Baldwin {
6206bc1e9cdSJohn Baldwin 	semid_t id;
6216bc1e9cdSJohn Baldwin 
6226bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
6236bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
6246bc1e9cdSJohn Baldwin 		return;
6256bc1e9cdSJohn Baldwin 	}
6266bc1e9cdSJohn Baldwin 
6276bc1e9cdSJohn Baldwin 	/* This should succeed and decrement the value to 0. */
6286bc1e9cdSJohn Baldwin 	if (ksem_trywait(id) < 0) {
6296bc1e9cdSJohn Baldwin 		fail_errno("ksem_trywait()");
6306bc1e9cdSJohn Baldwin 		ksem_destroy(id);
6316bc1e9cdSJohn Baldwin 		return;
6326bc1e9cdSJohn Baldwin 	}
6336bc1e9cdSJohn Baldwin 	if (checkvalue(id, 0) < 0) {
6346bc1e9cdSJohn Baldwin 		ksem_destroy(id);
6356bc1e9cdSJohn Baldwin 		return;
6366bc1e9cdSJohn Baldwin 	}
6376bc1e9cdSJohn Baldwin 
6386bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
6396bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
6406bc1e9cdSJohn Baldwin 		return;
6416bc1e9cdSJohn Baldwin 	}
6426bc1e9cdSJohn Baldwin 	pass();
6436bc1e9cdSJohn Baldwin }
6446bc1e9cdSJohn Baldwin TEST(unlocked_trywait, "unlocked trywait");
6456bc1e9cdSJohn Baldwin 
6466bc1e9cdSJohn Baldwin static void
locked_trywait(void)6476bc1e9cdSJohn Baldwin locked_trywait(void)
6486bc1e9cdSJohn Baldwin {
6496bc1e9cdSJohn Baldwin 	semid_t id;
6506bc1e9cdSJohn Baldwin 
6516bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 0) < 0) {
6526bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
6536bc1e9cdSJohn Baldwin 		return;
6546bc1e9cdSJohn Baldwin 	}
6556bc1e9cdSJohn Baldwin 
6566bc1e9cdSJohn Baldwin 	/* This should fail with EAGAIN and leave the value at 0. */
6576bc1e9cdSJohn Baldwin 	if (ksem_trywait(id) >= 0) {
6586bc1e9cdSJohn Baldwin 		fail_err("ksem_trywait() didn't fail");
6596bc1e9cdSJohn Baldwin 		ksem_destroy(id);
6606bc1e9cdSJohn Baldwin 		return;
6616bc1e9cdSJohn Baldwin 	}
6626bc1e9cdSJohn Baldwin 	if (errno != EAGAIN) {
6636bc1e9cdSJohn Baldwin 		fail_errno("wrong error from ksem_trywait()");
6646bc1e9cdSJohn Baldwin 		ksem_destroy(id);
6656bc1e9cdSJohn Baldwin 		return;
6666bc1e9cdSJohn Baldwin 	}
6676bc1e9cdSJohn Baldwin 	if (checkvalue(id, 0) < 0) {
6686bc1e9cdSJohn Baldwin 		ksem_destroy(id);
6696bc1e9cdSJohn Baldwin 		return;
6706bc1e9cdSJohn Baldwin 	}
6716bc1e9cdSJohn Baldwin 
6726bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
6736bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
6746bc1e9cdSJohn Baldwin 		return;
6756bc1e9cdSJohn Baldwin 	}
6766bc1e9cdSJohn Baldwin 	pass();
6776bc1e9cdSJohn Baldwin }
6786bc1e9cdSJohn Baldwin TEST(locked_trywait, "locked trywait");
6796bc1e9cdSJohn Baldwin 
6806bc1e9cdSJohn Baldwin /*
6816bc1e9cdSJohn Baldwin  * Use a timer to post a specific semaphore after a timeout.  A timer
6826bc1e9cdSJohn Baldwin  * is scheduled via schedule_post().  check_alarm() must be called
6836bc1e9cdSJohn Baldwin  * afterwards to clean up and check for errors.
6846bc1e9cdSJohn Baldwin  */
6856bc1e9cdSJohn Baldwin static semid_t alarm_id = -1;
6866bc1e9cdSJohn Baldwin static int alarm_errno;
6876bc1e9cdSJohn Baldwin static int alarm_handler_installed;
6886bc1e9cdSJohn Baldwin 
6896bc1e9cdSJohn Baldwin static void
alarm_handler(int signo)6906bc1e9cdSJohn Baldwin alarm_handler(int signo)
6916bc1e9cdSJohn Baldwin {
6926bc1e9cdSJohn Baldwin 
6936bc1e9cdSJohn Baldwin 	if (ksem_post(alarm_id) < 0)
6946bc1e9cdSJohn Baldwin 		alarm_errno = errno;
6956bc1e9cdSJohn Baldwin }
6966bc1e9cdSJohn Baldwin 
6976bc1e9cdSJohn Baldwin static int
check_alarm(int just_clear)6986bc1e9cdSJohn Baldwin check_alarm(int just_clear)
6996bc1e9cdSJohn Baldwin {
7006bc1e9cdSJohn Baldwin 	struct itimerval it;
7016bc1e9cdSJohn Baldwin 
7026bc1e9cdSJohn Baldwin 	bzero(&it, sizeof(it));
7036bc1e9cdSJohn Baldwin 	if (just_clear) {
7046bc1e9cdSJohn Baldwin 		setitimer(ITIMER_REAL, &it, NULL);
7056bc1e9cdSJohn Baldwin 		alarm_errno = 0;
7066bc1e9cdSJohn Baldwin 		alarm_id = -1;
7076bc1e9cdSJohn Baldwin 		return (0);
7086bc1e9cdSJohn Baldwin 	}
7096bc1e9cdSJohn Baldwin 	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
7106bc1e9cdSJohn Baldwin 		fail_errno("setitimer");
7116bc1e9cdSJohn Baldwin 		return (-1);
7126bc1e9cdSJohn Baldwin 	}
7136bc1e9cdSJohn Baldwin 	if (alarm_errno != 0 && !just_clear) {
7146bc1e9cdSJohn Baldwin 		errno = alarm_errno;
7156bc1e9cdSJohn Baldwin 		fail_errno("ksem_post() (via timeout)");
7166bc1e9cdSJohn Baldwin 		alarm_errno = 0;
7176bc1e9cdSJohn Baldwin 		return (-1);
7186bc1e9cdSJohn Baldwin 	}
7196bc1e9cdSJohn Baldwin 	alarm_id = -1;
7206bc1e9cdSJohn Baldwin 
7216bc1e9cdSJohn Baldwin 	return (0);
7226bc1e9cdSJohn Baldwin }
7236bc1e9cdSJohn Baldwin 
7246bc1e9cdSJohn Baldwin static int
schedule_post(semid_t id,u_int msec)7256bc1e9cdSJohn Baldwin schedule_post(semid_t id, u_int msec)
7266bc1e9cdSJohn Baldwin {
7276bc1e9cdSJohn Baldwin 	struct itimerval it;
7286bc1e9cdSJohn Baldwin 
7296bc1e9cdSJohn Baldwin 	if (!alarm_handler_installed) {
7306bc1e9cdSJohn Baldwin 		if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
7316bc1e9cdSJohn Baldwin 			fail_errno("signal(SIGALRM)");
7326bc1e9cdSJohn Baldwin 			return (-1);
7336bc1e9cdSJohn Baldwin 		}
7346bc1e9cdSJohn Baldwin 		alarm_handler_installed = 1;
7356bc1e9cdSJohn Baldwin 	}
7366bc1e9cdSJohn Baldwin 	if (alarm_id != -1) {
7376bc1e9cdSJohn Baldwin 		fail_err("ksem_post() already scheduled");
7386bc1e9cdSJohn Baldwin 		return (-1);
7396bc1e9cdSJohn Baldwin 	}
7406bc1e9cdSJohn Baldwin 	alarm_id = id;
7416bc1e9cdSJohn Baldwin 	bzero(&it, sizeof(it));
7426bc1e9cdSJohn Baldwin 	it.it_value.tv_sec = msec / 1000;
7436bc1e9cdSJohn Baldwin 	it.it_value.tv_usec = (msec % 1000) * 1000;
7446bc1e9cdSJohn Baldwin 	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
7456bc1e9cdSJohn Baldwin 		fail_errno("setitimer");
7466bc1e9cdSJohn Baldwin 		return (-1);
7476bc1e9cdSJohn Baldwin 	}
7486bc1e9cdSJohn Baldwin 	return (0);
7496bc1e9cdSJohn Baldwin }
7506bc1e9cdSJohn Baldwin 
7516bc1e9cdSJohn Baldwin static int
timedwait(semid_t id,u_int msec,u_int * delta,int error)7526bc1e9cdSJohn Baldwin timedwait(semid_t id, u_int msec, u_int *delta, int error)
7536bc1e9cdSJohn Baldwin {
7546bc1e9cdSJohn Baldwin 	struct timespec start, end;
7556bc1e9cdSJohn Baldwin 
7566bc1e9cdSJohn Baldwin 	if (clock_gettime(CLOCK_REALTIME, &start) < 0) {
7576bc1e9cdSJohn Baldwin 		fail_errno("clock_gettime(CLOCK_REALTIME)");
7586bc1e9cdSJohn Baldwin 		return (-1);
7596bc1e9cdSJohn Baldwin 	}
7606bc1e9cdSJohn Baldwin 	end.tv_sec = msec / 1000;
7616bc1e9cdSJohn Baldwin 	end.tv_nsec = msec % 1000 * 1000000;
762*6040822cSAlan Somers 	timespecadd(&end, &start, &end);
7636bc1e9cdSJohn Baldwin 	if (ksem_timedwait(id, &end) < 0) {
7646bc1e9cdSJohn Baldwin 		if (errno != error) {
7656bc1e9cdSJohn Baldwin 			fail_errno("ksem_timedwait");
7666bc1e9cdSJohn Baldwin 			return (-1);
7676bc1e9cdSJohn Baldwin 		}
7686bc1e9cdSJohn Baldwin 	} else if (error != 0) {
7696bc1e9cdSJohn Baldwin 		fail_err("ksem_timedwait() didn't fail");
7706bc1e9cdSJohn Baldwin 		return (-1);
7716bc1e9cdSJohn Baldwin 	}
7726bc1e9cdSJohn Baldwin 	if (clock_gettime(CLOCK_REALTIME, &end) < 0) {
7736bc1e9cdSJohn Baldwin 		fail_errno("clock_gettime(CLOCK_REALTIME)");
7746bc1e9cdSJohn Baldwin 		return (-1);
7756bc1e9cdSJohn Baldwin 	}
776*6040822cSAlan Somers 	timespecsub(&end, &start, &end);
7776bc1e9cdSJohn Baldwin 	*delta = end.tv_nsec / 1000000;
7786bc1e9cdSJohn Baldwin 	*delta += end.tv_sec * 1000;
7796bc1e9cdSJohn Baldwin 	return (0);
7806bc1e9cdSJohn Baldwin }
7816bc1e9cdSJohn Baldwin 
7826bc1e9cdSJohn Baldwin static void
unlocked_timedwait(void)7836bc1e9cdSJohn Baldwin unlocked_timedwait(void)
7846bc1e9cdSJohn Baldwin {
7856bc1e9cdSJohn Baldwin 	semid_t id;
7866bc1e9cdSJohn Baldwin 	u_int elapsed;
7876bc1e9cdSJohn Baldwin 
7886bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
7896bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
7906bc1e9cdSJohn Baldwin 		return;
7916bc1e9cdSJohn Baldwin 	}
7926bc1e9cdSJohn Baldwin 
7936bc1e9cdSJohn Baldwin 	/* This should succeed right away and set the value to 0. */
7946bc1e9cdSJohn Baldwin 	if (timedwait(id, 5000, &elapsed, 0) < 0) {
7956bc1e9cdSJohn Baldwin 		ksem_destroy(id);
7966bc1e9cdSJohn Baldwin 		return;
7976bc1e9cdSJohn Baldwin 	}
7986bc1e9cdSJohn Baldwin 	if (!ELAPSED(elapsed, 0)) {
7996bc1e9cdSJohn Baldwin 		fail_err("ksem_timedwait() of unlocked sem took %ums", elapsed);
8006bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8016bc1e9cdSJohn Baldwin 		return;
8026bc1e9cdSJohn Baldwin 	}
8036bc1e9cdSJohn Baldwin 	if (checkvalue(id, 0) < 0) {
8046bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8056bc1e9cdSJohn Baldwin 		return;
8066bc1e9cdSJohn Baldwin 	}
8076bc1e9cdSJohn Baldwin 
8086bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
8096bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
8106bc1e9cdSJohn Baldwin 		return;
8116bc1e9cdSJohn Baldwin 	}
8126bc1e9cdSJohn Baldwin 	pass();
8136bc1e9cdSJohn Baldwin }
8146bc1e9cdSJohn Baldwin TEST(unlocked_timedwait, "unlocked timedwait");
8156bc1e9cdSJohn Baldwin 
8166bc1e9cdSJohn Baldwin static void
expired_timedwait(void)8176bc1e9cdSJohn Baldwin expired_timedwait(void)
8186bc1e9cdSJohn Baldwin {
8196bc1e9cdSJohn Baldwin 	semid_t id;
8206bc1e9cdSJohn Baldwin 	u_int elapsed;
8216bc1e9cdSJohn Baldwin 
8226bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 0) < 0) {
8236bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
8246bc1e9cdSJohn Baldwin 		return;
8256bc1e9cdSJohn Baldwin 	}
8266bc1e9cdSJohn Baldwin 
8276bc1e9cdSJohn Baldwin 	/* This should fail with a timeout and leave the value at 0. */
8286bc1e9cdSJohn Baldwin 	if (timedwait(id, 2500, &elapsed, ETIMEDOUT) < 0) {
8296bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8306bc1e9cdSJohn Baldwin 		return;
8316bc1e9cdSJohn Baldwin 	}
8326bc1e9cdSJohn Baldwin 	if (!ELAPSED(elapsed, 2500)) {
8336bc1e9cdSJohn Baldwin 		fail_err(
8346bc1e9cdSJohn Baldwin 	    "ksem_timedwait() of locked sem took %ums instead of 2500ms",
8356bc1e9cdSJohn Baldwin 		    elapsed);
8366bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8376bc1e9cdSJohn Baldwin 		return;
8386bc1e9cdSJohn Baldwin 	}
8396bc1e9cdSJohn Baldwin 	if (checkvalue(id, 0) < 0) {
8406bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8416bc1e9cdSJohn Baldwin 		return;
8426bc1e9cdSJohn Baldwin 	}
8436bc1e9cdSJohn Baldwin 
8446bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
8456bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
8466bc1e9cdSJohn Baldwin 		return;
8476bc1e9cdSJohn Baldwin 	}
8486bc1e9cdSJohn Baldwin 	pass();
8496bc1e9cdSJohn Baldwin }
8506bc1e9cdSJohn Baldwin TEST(expired_timedwait, "locked timedwait timeout");
8516bc1e9cdSJohn Baldwin 
8526bc1e9cdSJohn Baldwin static void
locked_timedwait(void)8536bc1e9cdSJohn Baldwin locked_timedwait(void)
8546bc1e9cdSJohn Baldwin {
8556bc1e9cdSJohn Baldwin 	semid_t id;
8566bc1e9cdSJohn Baldwin 	u_int elapsed;
8576bc1e9cdSJohn Baldwin 
8586bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 0) < 0) {
8596bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
8606bc1e9cdSJohn Baldwin 		return;
8616bc1e9cdSJohn Baldwin 	}
8626bc1e9cdSJohn Baldwin 
8636bc1e9cdSJohn Baldwin 	/*
8646bc1e9cdSJohn Baldwin 	 * Schedule a post to trigger after 1000 ms.  The subsequent
8656bc1e9cdSJohn Baldwin 	 * timedwait should succeed after 1000 ms as a result w/o
8666bc1e9cdSJohn Baldwin 	 * timing out.
8676bc1e9cdSJohn Baldwin 	 */
8686bc1e9cdSJohn Baldwin 	if (schedule_post(id, 1000) < 0) {
8696bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8706bc1e9cdSJohn Baldwin 		return;
8716bc1e9cdSJohn Baldwin 	}
8726bc1e9cdSJohn Baldwin 	if (timedwait(id, 2000, &elapsed, 0) < 0) {
8736bc1e9cdSJohn Baldwin 		check_alarm(1);
8746bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8756bc1e9cdSJohn Baldwin 		return;
8766bc1e9cdSJohn Baldwin 	}
8776bc1e9cdSJohn Baldwin 	if (!ELAPSED(elapsed, 1000)) {
8786bc1e9cdSJohn Baldwin 		fail_err(
8796bc1e9cdSJohn Baldwin 	    "ksem_timedwait() with delayed post took %ums instead of 1000ms",
8806bc1e9cdSJohn Baldwin 		    elapsed);
8816bc1e9cdSJohn Baldwin 		check_alarm(1);
8826bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8836bc1e9cdSJohn Baldwin 		return;
8846bc1e9cdSJohn Baldwin 	}
8856bc1e9cdSJohn Baldwin 	if (check_alarm(0) < 0) {
8866bc1e9cdSJohn Baldwin 		ksem_destroy(id);
8876bc1e9cdSJohn Baldwin 		return;
8886bc1e9cdSJohn Baldwin 	}
8896bc1e9cdSJohn Baldwin 
8906bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
8916bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
8926bc1e9cdSJohn Baldwin 		return;
8936bc1e9cdSJohn Baldwin 	}
8946bc1e9cdSJohn Baldwin 	pass();
8956bc1e9cdSJohn Baldwin }
8966bc1e9cdSJohn Baldwin TEST(locked_timedwait, "locked timedwait");
8976bc1e9cdSJohn Baldwin 
8986bc1e9cdSJohn Baldwin static int
testwait(semid_t id,u_int * delta)8996bc1e9cdSJohn Baldwin testwait(semid_t id, u_int *delta)
9006bc1e9cdSJohn Baldwin {
9016bc1e9cdSJohn Baldwin 	struct timespec start, end;
9026bc1e9cdSJohn Baldwin 
9036bc1e9cdSJohn Baldwin 	if (clock_gettime(CLOCK_REALTIME, &start) < 0) {
9046bc1e9cdSJohn Baldwin 		fail_errno("clock_gettime(CLOCK_REALTIME)");
9056bc1e9cdSJohn Baldwin 		return (-1);
9066bc1e9cdSJohn Baldwin 	}
9076bc1e9cdSJohn Baldwin 	if (ksem_wait(id) < 0) {
9086bc1e9cdSJohn Baldwin 		fail_errno("ksem_wait");
9096bc1e9cdSJohn Baldwin 		return (-1);
9106bc1e9cdSJohn Baldwin 	}
9116bc1e9cdSJohn Baldwin 	if (clock_gettime(CLOCK_REALTIME, &end) < 0) {
9126bc1e9cdSJohn Baldwin 		fail_errno("clock_gettime(CLOCK_REALTIME)");
9136bc1e9cdSJohn Baldwin 		return (-1);
9146bc1e9cdSJohn Baldwin 	}
915*6040822cSAlan Somers 	timespecsub(&end, &start, &end);
9166bc1e9cdSJohn Baldwin 	*delta = end.tv_nsec / 1000000;
9176bc1e9cdSJohn Baldwin 	*delta += end.tv_sec * 1000;
9186bc1e9cdSJohn Baldwin 	return (0);
9196bc1e9cdSJohn Baldwin }
9206bc1e9cdSJohn Baldwin 
9216bc1e9cdSJohn Baldwin static void
unlocked_wait(void)9226bc1e9cdSJohn Baldwin unlocked_wait(void)
9236bc1e9cdSJohn Baldwin {
9246bc1e9cdSJohn Baldwin 	semid_t id;
9256bc1e9cdSJohn Baldwin 	u_int elapsed;
9266bc1e9cdSJohn Baldwin 
9276bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 1) < 0) {
9286bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
9296bc1e9cdSJohn Baldwin 		return;
9306bc1e9cdSJohn Baldwin 	}
9316bc1e9cdSJohn Baldwin 
9326bc1e9cdSJohn Baldwin 	/* This should succeed right away and set the value to 0. */
9336bc1e9cdSJohn Baldwin 	if (testwait(id, &elapsed) < 0) {
9346bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9356bc1e9cdSJohn Baldwin 		return;
9366bc1e9cdSJohn Baldwin 	}
9376bc1e9cdSJohn Baldwin 	if (!ELAPSED(elapsed, 0)) {
9386bc1e9cdSJohn Baldwin 		fail_err("ksem_wait() of unlocked sem took %ums", elapsed);
9396bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9406bc1e9cdSJohn Baldwin 		return;
9416bc1e9cdSJohn Baldwin 	}
9426bc1e9cdSJohn Baldwin 	if (checkvalue(id, 0) < 0) {
9436bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9446bc1e9cdSJohn Baldwin 		return;
9456bc1e9cdSJohn Baldwin 	}
9466bc1e9cdSJohn Baldwin 
9476bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
9486bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
9496bc1e9cdSJohn Baldwin 		return;
9506bc1e9cdSJohn Baldwin 	}
9516bc1e9cdSJohn Baldwin 	pass();
9526bc1e9cdSJohn Baldwin }
9536bc1e9cdSJohn Baldwin TEST(unlocked_wait, "unlocked wait");
9546bc1e9cdSJohn Baldwin 
9556bc1e9cdSJohn Baldwin static void
locked_wait(void)9566bc1e9cdSJohn Baldwin locked_wait(void)
9576bc1e9cdSJohn Baldwin {
9586bc1e9cdSJohn Baldwin 	semid_t id;
9596bc1e9cdSJohn Baldwin 	u_int elapsed;
9606bc1e9cdSJohn Baldwin 
9616bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 0) < 0) {
9626bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
9636bc1e9cdSJohn Baldwin 		return;
9646bc1e9cdSJohn Baldwin 	}
9656bc1e9cdSJohn Baldwin 
9666bc1e9cdSJohn Baldwin 	/*
9676bc1e9cdSJohn Baldwin 	 * Schedule a post to trigger after 1000 ms.  The subsequent
9686bc1e9cdSJohn Baldwin 	 * wait should succeed after 1000 ms as a result.
9696bc1e9cdSJohn Baldwin 	 */
9706bc1e9cdSJohn Baldwin 	if (schedule_post(id, 1000) < 0) {
9716bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9726bc1e9cdSJohn Baldwin 		return;
9736bc1e9cdSJohn Baldwin 	}
9746bc1e9cdSJohn Baldwin 	if (testwait(id, &elapsed) < 0) {
9756bc1e9cdSJohn Baldwin 		check_alarm(1);
9766bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9776bc1e9cdSJohn Baldwin 		return;
9786bc1e9cdSJohn Baldwin 	}
9796bc1e9cdSJohn Baldwin 	if (!ELAPSED(elapsed, 1000)) {
9806bc1e9cdSJohn Baldwin 		fail_err(
9816bc1e9cdSJohn Baldwin 	    "ksem_wait() with delayed post took %ums instead of 1000ms",
9826bc1e9cdSJohn Baldwin 		    elapsed);
9836bc1e9cdSJohn Baldwin 		check_alarm(1);
9846bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9856bc1e9cdSJohn Baldwin 		return;
9866bc1e9cdSJohn Baldwin 	}
9876bc1e9cdSJohn Baldwin 	if (check_alarm(0) < 0) {
9886bc1e9cdSJohn Baldwin 		ksem_destroy(id);
9896bc1e9cdSJohn Baldwin 		return;
9906bc1e9cdSJohn Baldwin 	}
9916bc1e9cdSJohn Baldwin 
9926bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
9936bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
9946bc1e9cdSJohn Baldwin 		return;
9956bc1e9cdSJohn Baldwin 	}
9966bc1e9cdSJohn Baldwin 	pass();
9976bc1e9cdSJohn Baldwin }
9986bc1e9cdSJohn Baldwin TEST(locked_wait, "locked wait");
9996bc1e9cdSJohn Baldwin 
10006bc1e9cdSJohn Baldwin /*
10016bc1e9cdSJohn Baldwin  * Fork off a child process.  The child will open the semaphore via
10026bc1e9cdSJohn Baldwin  * the same name.  The child will then block on the semaphore waiting
10036bc1e9cdSJohn Baldwin  * for the parent to post it.
10046bc1e9cdSJohn Baldwin  */
10056bc1e9cdSJohn Baldwin static int
wait_twoproc_child(void * arg)10066bc1e9cdSJohn Baldwin wait_twoproc_child(void *arg)
10076bc1e9cdSJohn Baldwin {
10086bc1e9cdSJohn Baldwin 	semid_t id;
10096bc1e9cdSJohn Baldwin 
10106bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, 0, 0, 0) < 0)
10116bc1e9cdSJohn Baldwin 		return (CSTAT(1, errno));
10126bc1e9cdSJohn Baldwin 	if (ksem_wait(id) < 0)
10136bc1e9cdSJohn Baldwin 		return (CSTAT(2, errno));
10146bc1e9cdSJohn Baldwin 	if (ksem_close(id) < 0)
10156bc1e9cdSJohn Baldwin 		return (CSTAT(3, errno));
10166bc1e9cdSJohn Baldwin 	return (CSTAT(0, 0));
10176bc1e9cdSJohn Baldwin }
10186bc1e9cdSJohn Baldwin 
10196bc1e9cdSJohn Baldwin static void
wait_twoproc_test(void)10206bc1e9cdSJohn Baldwin wait_twoproc_test(void)
10216bc1e9cdSJohn Baldwin {
10226bc1e9cdSJohn Baldwin 	semid_t id;
10236bc1e9cdSJohn Baldwin 	int stat;
10246bc1e9cdSJohn Baldwin 
10256bc1e9cdSJohn Baldwin 	if (ksem_open(&id, TEST_PATH, O_CREAT, 0777, 0)) {
10266bc1e9cdSJohn Baldwin 		fail_errno("ksem_open");
10276bc1e9cdSJohn Baldwin 		return;
10286bc1e9cdSJohn Baldwin 	}
10296bc1e9cdSJohn Baldwin 
10306bc1e9cdSJohn Baldwin 	if (schedule_post(id, 500) < 0) {
10316bc1e9cdSJohn Baldwin 		ksem_close(id);
10326bc1e9cdSJohn Baldwin 		ksem_unlink(TEST_PATH);
10336bc1e9cdSJohn Baldwin 		return;
10346bc1e9cdSJohn Baldwin 	}
10356bc1e9cdSJohn Baldwin 
10366bc1e9cdSJohn Baldwin 	if (child_worker(wait_twoproc_child, NULL, &stat) < 0) {
10376bc1e9cdSJohn Baldwin 		check_alarm(1);
10386bc1e9cdSJohn Baldwin 		ksem_close(id);
10396bc1e9cdSJohn Baldwin 		ksem_unlink(TEST_PATH);
10406bc1e9cdSJohn Baldwin 		return;
10416bc1e9cdSJohn Baldwin 	}
10426bc1e9cdSJohn Baldwin 
10436bc1e9cdSJohn Baldwin 	errno = CSTAT_ERROR(stat);
10446bc1e9cdSJohn Baldwin 	switch (CSTAT_CLASS(stat)) {
10456bc1e9cdSJohn Baldwin 	case 0:
10466bc1e9cdSJohn Baldwin 		pass();
10476bc1e9cdSJohn Baldwin 		break;
10486bc1e9cdSJohn Baldwin 	case 1:
10496bc1e9cdSJohn Baldwin 		fail_errno("child ksem_open()");
10506bc1e9cdSJohn Baldwin 		break;
10516bc1e9cdSJohn Baldwin 	case 2:
10526bc1e9cdSJohn Baldwin 		fail_errno("child ksem_wait()");
10536bc1e9cdSJohn Baldwin 		break;
10546bc1e9cdSJohn Baldwin 	case 3:
10556bc1e9cdSJohn Baldwin 		fail_errno("child ksem_close()");
10566bc1e9cdSJohn Baldwin 		break;
10576bc1e9cdSJohn Baldwin 	default:
10586bc1e9cdSJohn Baldwin 		fail_err("bad child state %#x", stat);
10596bc1e9cdSJohn Baldwin 		break;
10606bc1e9cdSJohn Baldwin 	}
10616bc1e9cdSJohn Baldwin 
10626bc1e9cdSJohn Baldwin 	check_alarm(1);
10636bc1e9cdSJohn Baldwin 	ksem_close(id);
10646bc1e9cdSJohn Baldwin 	ksem_unlink(TEST_PATH);
10656bc1e9cdSJohn Baldwin }
10666bc1e9cdSJohn Baldwin TEST(wait_twoproc_test, "two proc wait");
10676bc1e9cdSJohn Baldwin 
10686bc1e9cdSJohn Baldwin static void
maxvalue_test(void)10696bc1e9cdSJohn Baldwin maxvalue_test(void)
10706bc1e9cdSJohn Baldwin {
10716bc1e9cdSJohn Baldwin 	semid_t id;
10726bc1e9cdSJohn Baldwin 	int val;
10736bc1e9cdSJohn Baldwin 
10746bc1e9cdSJohn Baldwin 	if (ksem_init(&id, SEM_VALUE_MAX) < 0) {
10756bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
10766bc1e9cdSJohn Baldwin 		return;
10776bc1e9cdSJohn Baldwin 	}
10786bc1e9cdSJohn Baldwin 	if (ksem_getvalue(id, &val) < 0) {
10796bc1e9cdSJohn Baldwin 		fail_errno("ksem_getvalue");
10806bc1e9cdSJohn Baldwin 		ksem_destroy(id);
10816bc1e9cdSJohn Baldwin 		return;
10826bc1e9cdSJohn Baldwin 	}
10836bc1e9cdSJohn Baldwin 	if (val != SEM_VALUE_MAX) {
10846bc1e9cdSJohn Baldwin 		fail_err("value %d != SEM_VALUE_MAX");
10856bc1e9cdSJohn Baldwin 		ksem_destroy(id);
10866bc1e9cdSJohn Baldwin 		return;
10876bc1e9cdSJohn Baldwin 	}
10886bc1e9cdSJohn Baldwin 	if (val < 0) {
10896bc1e9cdSJohn Baldwin 		fail_err("value < 0");
10906bc1e9cdSJohn Baldwin 		ksem_destroy(id);
10916bc1e9cdSJohn Baldwin 		return;
10926bc1e9cdSJohn Baldwin 	}
10936bc1e9cdSJohn Baldwin 	if (ksem_destroy(id) < 0) {
10946bc1e9cdSJohn Baldwin 		fail_errno("ksem_destroy");
10956bc1e9cdSJohn Baldwin 		return;
10966bc1e9cdSJohn Baldwin 	}
10976bc1e9cdSJohn Baldwin 	pass();
10986bc1e9cdSJohn Baldwin }
10996bc1e9cdSJohn Baldwin TEST(maxvalue_test, "get value of SEM_VALUE_MAX semaphore");
11006bc1e9cdSJohn Baldwin 
11016bc1e9cdSJohn Baldwin static void
maxvalue_post_test(void)11026bc1e9cdSJohn Baldwin maxvalue_post_test(void)
11036bc1e9cdSJohn Baldwin {
11046bc1e9cdSJohn Baldwin 	semid_t id;
11056bc1e9cdSJohn Baldwin 
11066bc1e9cdSJohn Baldwin 	if (ksem_init(&id, SEM_VALUE_MAX) < 0) {
11076bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
11086bc1e9cdSJohn Baldwin 		return;
11096bc1e9cdSJohn Baldwin 	}
11106bc1e9cdSJohn Baldwin 
11116bc1e9cdSJohn Baldwin 	ksem_post_should_fail(id, EOVERFLOW);
11126bc1e9cdSJohn Baldwin 
11136bc1e9cdSJohn Baldwin 	ksem_destroy(id);
11146bc1e9cdSJohn Baldwin }
11156bc1e9cdSJohn Baldwin TEST(maxvalue_post_test, "post SEM_VALUE_MAX semaphore");
11166bc1e9cdSJohn Baldwin 
11176bc1e9cdSJohn Baldwin static void
busy_destroy_test(void)11186bc1e9cdSJohn Baldwin busy_destroy_test(void)
11196bc1e9cdSJohn Baldwin {
11206bc1e9cdSJohn Baldwin 	char errbuf[_POSIX2_LINE_MAX];
11216bc1e9cdSJohn Baldwin 	struct kinfo_proc *kp;
11226bc1e9cdSJohn Baldwin 	semid_t id;
11236bc1e9cdSJohn Baldwin 	pid_t pid;
11246bc1e9cdSJohn Baldwin 	kvm_t *kd;
11256bc1e9cdSJohn Baldwin 	int count;
11266bc1e9cdSJohn Baldwin 
11276bc1e9cdSJohn Baldwin 	kd = kvm_openfiles(NULL, "/dev/null", NULL, O_RDONLY, errbuf);
11286bc1e9cdSJohn Baldwin 	if (kd == NULL) {
11296bc1e9cdSJohn Baldwin 		fail_err("kvm_openfiles: %s", errbuf);
11306bc1e9cdSJohn Baldwin 		return;
11316bc1e9cdSJohn Baldwin 	}
11326bc1e9cdSJohn Baldwin 
11336bc1e9cdSJohn Baldwin 	if (ksem_init(&id, 0) < 0) {
11346bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
11356bc1e9cdSJohn Baldwin 		kvm_close(kd);
11366bc1e9cdSJohn Baldwin 		return;
11376bc1e9cdSJohn Baldwin 	}
11386bc1e9cdSJohn Baldwin 
11396bc1e9cdSJohn Baldwin 	pid = fork();
11406bc1e9cdSJohn Baldwin 	switch (pid) {
11416bc1e9cdSJohn Baldwin 	case -1:
11426bc1e9cdSJohn Baldwin 		/* Error. */
11436bc1e9cdSJohn Baldwin 		fail_errno("fork");
11446bc1e9cdSJohn Baldwin 		ksem_destroy(id);
11456bc1e9cdSJohn Baldwin 		kvm_close(kd);
11466bc1e9cdSJohn Baldwin 		return;
11476bc1e9cdSJohn Baldwin 	case 0:
11486bc1e9cdSJohn Baldwin 		/* Child. */
11496bc1e9cdSJohn Baldwin 		ksem_wait(id);
11506bc1e9cdSJohn Baldwin 		exit(0);
11516bc1e9cdSJohn Baldwin 	}
11526bc1e9cdSJohn Baldwin 
11536bc1e9cdSJohn Baldwin 	/*
11546bc1e9cdSJohn Baldwin 	 * Wait for the child process to block on the semaphore.  This
11556bc1e9cdSJohn Baldwin 	 * is a bit gross.
11566bc1e9cdSJohn Baldwin 	 */
11576bc1e9cdSJohn Baldwin 	for (;;) {
11586bc1e9cdSJohn Baldwin 		kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &count);
11596bc1e9cdSJohn Baldwin 		if (kp == NULL) {
11606bc1e9cdSJohn Baldwin 			fail_err("kvm_getprocs: %s", kvm_geterr(kd));
11616bc1e9cdSJohn Baldwin 			kvm_close(kd);
11626bc1e9cdSJohn Baldwin 			ksem_destroy(id);
11636bc1e9cdSJohn Baldwin 			return;
11646bc1e9cdSJohn Baldwin 		}
11656bc1e9cdSJohn Baldwin 		if (kp->ki_stat == SSLEEP &&
11666bc1e9cdSJohn Baldwin 		    (strcmp(kp->ki_wmesg, "sem") == 0 ||
11676bc1e9cdSJohn Baldwin 		    strcmp(kp->ki_wmesg, "ksem") == 0))
11686bc1e9cdSJohn Baldwin 			break;
11696bc1e9cdSJohn Baldwin 		usleep(1000);
11706bc1e9cdSJohn Baldwin 	}
11716bc1e9cdSJohn Baldwin 	kvm_close(kd);
11726bc1e9cdSJohn Baldwin 
11736bc1e9cdSJohn Baldwin 	ksem_destroy_should_fail(id, EBUSY);
11746bc1e9cdSJohn Baldwin 
11756bc1e9cdSJohn Baldwin 	/* Cleanup. */
11766bc1e9cdSJohn Baldwin 	ksem_post(id);
11776bc1e9cdSJohn Baldwin 	waitpid(pid, NULL, 0);
11786bc1e9cdSJohn Baldwin 	ksem_destroy(id);
11796bc1e9cdSJohn Baldwin }
11806bc1e9cdSJohn Baldwin TEST(busy_destroy_test, "destroy unnamed semaphore with waiter");
11816bc1e9cdSJohn Baldwin 
11826bc1e9cdSJohn Baldwin static int
exhaust_unnamed_child(void * arg)11836bc1e9cdSJohn Baldwin exhaust_unnamed_child(void *arg)
11846bc1e9cdSJohn Baldwin {
11856bc1e9cdSJohn Baldwin 	semid_t id;
11866bc1e9cdSJohn Baldwin 	int i, max;
11876bc1e9cdSJohn Baldwin 
11886bc1e9cdSJohn Baldwin 	max = (intptr_t)arg;
11896bc1e9cdSJohn Baldwin 	for (i = 0; i < max + 1; i++) {
11906bc1e9cdSJohn Baldwin 		if (ksem_init(&id, 1) < 0) {
11916bc1e9cdSJohn Baldwin 			if (errno == ENOSPC)
11926bc1e9cdSJohn Baldwin 				return (CSTAT(0, 0));
11936bc1e9cdSJohn Baldwin 			return (CSTAT(1, errno));
11946bc1e9cdSJohn Baldwin 		}
11956bc1e9cdSJohn Baldwin 	}
11966bc1e9cdSJohn Baldwin 	return (CSTAT(2, 0));
11976bc1e9cdSJohn Baldwin }
11986bc1e9cdSJohn Baldwin 
11996bc1e9cdSJohn Baldwin static void
exhaust_unnamed_sems(void)12006bc1e9cdSJohn Baldwin exhaust_unnamed_sems(void)
12016bc1e9cdSJohn Baldwin {
12026bc1e9cdSJohn Baldwin 	size_t len;
12036bc1e9cdSJohn Baldwin 	int nsems_max, stat;
12046bc1e9cdSJohn Baldwin 
12056bc1e9cdSJohn Baldwin 	len = sizeof(nsems_max);
12066bc1e9cdSJohn Baldwin 	if (sysctlbyname("p1003_1b.sem_nsems_max", &nsems_max, &len, NULL, 0) <
12076bc1e9cdSJohn Baldwin 	    0) {
12086bc1e9cdSJohn Baldwin 		fail_errno("sysctl(p1003_1b.sem_nsems_max)");
12096bc1e9cdSJohn Baldwin 		return;
12106bc1e9cdSJohn Baldwin 	}
12116bc1e9cdSJohn Baldwin 
121231f95703SKonstantin Belousov 	if (child_worker(exhaust_unnamed_child, (void *)(uintptr_t)nsems_max,
121331f95703SKonstantin Belousov 	    &stat))
12146bc1e9cdSJohn Baldwin 		return;
12156bc1e9cdSJohn Baldwin 	errno = CSTAT_ERROR(stat);
12166bc1e9cdSJohn Baldwin 	switch (CSTAT_CLASS(stat)) {
12176bc1e9cdSJohn Baldwin 	case 0:
12186bc1e9cdSJohn Baldwin 		pass();
12196bc1e9cdSJohn Baldwin 		break;
12206bc1e9cdSJohn Baldwin 	case 1:
12216bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
12226bc1e9cdSJohn Baldwin 		break;
12236bc1e9cdSJohn Baldwin 	case 2:
12246bc1e9cdSJohn Baldwin 		fail_err("Limit of %d semaphores not enforced", nsems_max);
12256bc1e9cdSJohn Baldwin 		break;
12266bc1e9cdSJohn Baldwin 	default:
12276bc1e9cdSJohn Baldwin 		fail_err("bad child state %#x", stat);
12286bc1e9cdSJohn Baldwin 		break;
12296bc1e9cdSJohn Baldwin 	}
12306bc1e9cdSJohn Baldwin }
12316bc1e9cdSJohn Baldwin TEST(exhaust_unnamed_sems, "exhaust unnamed semaphores (1)");
12326bc1e9cdSJohn Baldwin 
12336bc1e9cdSJohn Baldwin static int
exhaust_named_child(void * arg)12346bc1e9cdSJohn Baldwin exhaust_named_child(void *arg)
12356bc1e9cdSJohn Baldwin {
12366bc1e9cdSJohn Baldwin 	char buffer[64];
12376bc1e9cdSJohn Baldwin 	semid_t id;
12386bc1e9cdSJohn Baldwin 	int i, max;
12396bc1e9cdSJohn Baldwin 
12406bc1e9cdSJohn Baldwin 	max = (intptr_t)arg;
12416bc1e9cdSJohn Baldwin 	for (i = 0; i < max + 1; i++) {
12426bc1e9cdSJohn Baldwin 		snprintf(buffer, sizeof(buffer), "%s%d", TEST_PATH, i);
12436bc1e9cdSJohn Baldwin 		if (ksem_open(&id, buffer, O_CREAT, 0777, 1) < 0) {
12446bc1e9cdSJohn Baldwin 			if (errno == ENOSPC || errno == EMFILE ||
12456bc1e9cdSJohn Baldwin 			    errno == ENFILE)
12466bc1e9cdSJohn Baldwin 				return (CSTAT(0, 0));
12476bc1e9cdSJohn Baldwin 			return (CSTAT(1, errno));
12486bc1e9cdSJohn Baldwin 		}
12496bc1e9cdSJohn Baldwin 	}
12506bc1e9cdSJohn Baldwin 	return (CSTAT(2, errno));
12516bc1e9cdSJohn Baldwin }
12526bc1e9cdSJohn Baldwin 
12536bc1e9cdSJohn Baldwin static void
exhaust_named_sems(void)12546bc1e9cdSJohn Baldwin exhaust_named_sems(void)
12556bc1e9cdSJohn Baldwin {
12566bc1e9cdSJohn Baldwin 	char buffer[64];
12576bc1e9cdSJohn Baldwin 	size_t len;
12586bc1e9cdSJohn Baldwin 	int i, nsems_max, stat;
12596bc1e9cdSJohn Baldwin 
12606bc1e9cdSJohn Baldwin 	len = sizeof(nsems_max);
12616bc1e9cdSJohn Baldwin 	if (sysctlbyname("p1003_1b.sem_nsems_max", &nsems_max, &len, NULL, 0) <
12626bc1e9cdSJohn Baldwin 	    0) {
12636bc1e9cdSJohn Baldwin 		fail_errno("sysctl(p1003_1b.sem_nsems_max)");
12646bc1e9cdSJohn Baldwin 		return;
12656bc1e9cdSJohn Baldwin 	}
12666bc1e9cdSJohn Baldwin 
126731f95703SKonstantin Belousov 	if (child_worker(exhaust_named_child, (void *)(uintptr_t)nsems_max,
126831f95703SKonstantin Belousov 	    &stat) < 0)
12696bc1e9cdSJohn Baldwin 		return;
12706bc1e9cdSJohn Baldwin 	errno = CSTAT_ERROR(stat);
12716bc1e9cdSJohn Baldwin 	switch (CSTAT_CLASS(stat)) {
12726bc1e9cdSJohn Baldwin 	case 0:
12736bc1e9cdSJohn Baldwin 		pass();
12746bc1e9cdSJohn Baldwin 		break;
12756bc1e9cdSJohn Baldwin 	case 1:
12766bc1e9cdSJohn Baldwin 		fail_errno("ksem_open");
12776bc1e9cdSJohn Baldwin 		break;
12786bc1e9cdSJohn Baldwin 	case 2:
12796bc1e9cdSJohn Baldwin 		fail_err("Limit of %d semaphores not enforced", nsems_max);
12806bc1e9cdSJohn Baldwin 		break;
12816bc1e9cdSJohn Baldwin 	default:
12826bc1e9cdSJohn Baldwin 		fail_err("bad child state %#x", stat);
12836bc1e9cdSJohn Baldwin 		break;
12846bc1e9cdSJohn Baldwin 	}
12856bc1e9cdSJohn Baldwin 
12866bc1e9cdSJohn Baldwin 	/* Cleanup any semaphores created by the child. */
12876bc1e9cdSJohn Baldwin 	for (i = 0; i < nsems_max + 1; i++) {
12886bc1e9cdSJohn Baldwin 		snprintf(buffer, sizeof(buffer), "%s%d", TEST_PATH, i);
12896bc1e9cdSJohn Baldwin 		ksem_unlink(buffer);
12906bc1e9cdSJohn Baldwin 	}
12916bc1e9cdSJohn Baldwin }
12926bc1e9cdSJohn Baldwin TEST(exhaust_named_sems, "exhaust named semaphores (1)");
12936bc1e9cdSJohn Baldwin 
12946bc1e9cdSJohn Baldwin static int
fdlimit_set(void * arg)12956bc1e9cdSJohn Baldwin fdlimit_set(void *arg)
12966bc1e9cdSJohn Baldwin {
12976bc1e9cdSJohn Baldwin 	struct rlimit rlim;
12986bc1e9cdSJohn Baldwin 	int max;
12996bc1e9cdSJohn Baldwin 
13006bc1e9cdSJohn Baldwin 	max = (intptr_t)arg;
13016bc1e9cdSJohn Baldwin 	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
13026bc1e9cdSJohn Baldwin 		return (CSTAT(3, errno));
13036bc1e9cdSJohn Baldwin 	rlim.rlim_cur = max;
13046bc1e9cdSJohn Baldwin 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
13056bc1e9cdSJohn Baldwin 		return (CSTAT(4, errno));
13066bc1e9cdSJohn Baldwin 	return (0);
13076bc1e9cdSJohn Baldwin }
13086bc1e9cdSJohn Baldwin 
13096bc1e9cdSJohn Baldwin static int
fdlimit_unnamed_child(void * arg)13106bc1e9cdSJohn Baldwin fdlimit_unnamed_child(void *arg)
13116bc1e9cdSJohn Baldwin {
13126bc1e9cdSJohn Baldwin 	int stat;
13136bc1e9cdSJohn Baldwin 
13146bc1e9cdSJohn Baldwin 	stat = fdlimit_set(arg);
13156bc1e9cdSJohn Baldwin 	if (stat == 0)
13166bc1e9cdSJohn Baldwin 		stat = exhaust_unnamed_child(arg);
13176bc1e9cdSJohn Baldwin 	return (stat);
13186bc1e9cdSJohn Baldwin }
13196bc1e9cdSJohn Baldwin 
13206bc1e9cdSJohn Baldwin static void
fdlimit_unnamed_sems(void)13216bc1e9cdSJohn Baldwin fdlimit_unnamed_sems(void)
13226bc1e9cdSJohn Baldwin {
13236bc1e9cdSJohn Baldwin 	int nsems_max, stat;
13246bc1e9cdSJohn Baldwin 
13256bc1e9cdSJohn Baldwin 	nsems_max = 10;
132631f95703SKonstantin Belousov 	if (child_worker(fdlimit_unnamed_child, (void *)(uintptr_t)nsems_max,
132731f95703SKonstantin Belousov 	    &stat))
13286bc1e9cdSJohn Baldwin 		return;
13296bc1e9cdSJohn Baldwin 	errno = CSTAT_ERROR(stat);
13306bc1e9cdSJohn Baldwin 	switch (CSTAT_CLASS(stat)) {
13316bc1e9cdSJohn Baldwin 	case 0:
13326bc1e9cdSJohn Baldwin 		pass();
13336bc1e9cdSJohn Baldwin 		break;
13346bc1e9cdSJohn Baldwin 	case 1:
13356bc1e9cdSJohn Baldwin 		fail_errno("ksem_init");
13366bc1e9cdSJohn Baldwin 		break;
13376bc1e9cdSJohn Baldwin 	case 2:
13386bc1e9cdSJohn Baldwin 		fail_err("Limit of %d semaphores not enforced", nsems_max);
13396bc1e9cdSJohn Baldwin 		break;
13406bc1e9cdSJohn Baldwin 	case 3:
13416bc1e9cdSJohn Baldwin 		fail_errno("getrlimit");
13426bc1e9cdSJohn Baldwin 		break;
13436bc1e9cdSJohn Baldwin 	case 4:
13446bc1e9cdSJohn Baldwin 		fail_errno("getrlimit");
13456bc1e9cdSJohn Baldwin 		break;
13466bc1e9cdSJohn Baldwin 	default:
13476bc1e9cdSJohn Baldwin 		fail_err("bad child state %#x", stat);
13486bc1e9cdSJohn Baldwin 		break;
13496bc1e9cdSJohn Baldwin 	}
13506bc1e9cdSJohn Baldwin }
13516bc1e9cdSJohn Baldwin TEST(fdlimit_unnamed_sems, "exhaust unnamed semaphores (2)");
13526bc1e9cdSJohn Baldwin 
13536bc1e9cdSJohn Baldwin static int
fdlimit_named_child(void * arg)13546bc1e9cdSJohn Baldwin fdlimit_named_child(void *arg)
13556bc1e9cdSJohn Baldwin {
13566bc1e9cdSJohn Baldwin 	int stat;
13576bc1e9cdSJohn Baldwin 
13586bc1e9cdSJohn Baldwin 	stat = fdlimit_set(arg);
13596bc1e9cdSJohn Baldwin 	if (stat == 0)
13606bc1e9cdSJohn Baldwin 		stat = exhaust_named_child(arg);
13616bc1e9cdSJohn Baldwin 	return (stat);
13626bc1e9cdSJohn Baldwin }
13636bc1e9cdSJohn Baldwin 
13646bc1e9cdSJohn Baldwin static void
fdlimit_named_sems(void)13656bc1e9cdSJohn Baldwin fdlimit_named_sems(void)
13666bc1e9cdSJohn Baldwin {
13676bc1e9cdSJohn Baldwin 	char buffer[64];
13686bc1e9cdSJohn Baldwin 	int i, nsems_max, stat;
13696bc1e9cdSJohn Baldwin 
13706bc1e9cdSJohn Baldwin 	nsems_max = 10;
137131f95703SKonstantin Belousov 	if (child_worker(fdlimit_named_child, (void *)(uintptr_t)nsems_max,
137231f95703SKonstantin Belousov 	    &stat) < 0)
13736bc1e9cdSJohn Baldwin 		return;
13746bc1e9cdSJohn Baldwin 	errno = CSTAT_ERROR(stat);
13756bc1e9cdSJohn Baldwin 	switch (CSTAT_CLASS(stat)) {
13766bc1e9cdSJohn Baldwin 	case 0:
13776bc1e9cdSJohn Baldwin 		pass();
13786bc1e9cdSJohn Baldwin 		break;
13796bc1e9cdSJohn Baldwin 	case 1:
13806bc1e9cdSJohn Baldwin 		fail_errno("ksem_open");
13816bc1e9cdSJohn Baldwin 		break;
13826bc1e9cdSJohn Baldwin 	case 2:
13836bc1e9cdSJohn Baldwin 		fail_err("Limit of %d semaphores not enforced", nsems_max);
13846bc1e9cdSJohn Baldwin 		break;
13856bc1e9cdSJohn Baldwin 	case 3:
13866bc1e9cdSJohn Baldwin 		fail_errno("getrlimit");
13876bc1e9cdSJohn Baldwin 		break;
13886bc1e9cdSJohn Baldwin 	case 4:
13896bc1e9cdSJohn Baldwin 		fail_errno("getrlimit");
13906bc1e9cdSJohn Baldwin 		break;
13916bc1e9cdSJohn Baldwin 	default:
13926bc1e9cdSJohn Baldwin 		fail_err("bad child state %#x", stat);
13936bc1e9cdSJohn Baldwin 		break;
13946bc1e9cdSJohn Baldwin 	}
13956bc1e9cdSJohn Baldwin 
13966bc1e9cdSJohn Baldwin 	/* Cleanup any semaphores created by the child. */
13976bc1e9cdSJohn Baldwin 	for (i = 0; i < nsems_max + 1; i++) {
13986bc1e9cdSJohn Baldwin 		snprintf(buffer, sizeof(buffer), "%s%d", TEST_PATH, i);
13996bc1e9cdSJohn Baldwin 		ksem_unlink(buffer);
14006bc1e9cdSJohn Baldwin 	}
14016bc1e9cdSJohn Baldwin }
14026bc1e9cdSJohn Baldwin TEST(fdlimit_named_sems, "exhaust named semaphores (2)");
14036bc1e9cdSJohn Baldwin 
14046bc1e9cdSJohn Baldwin int
main(int argc,char * argv[])14056bc1e9cdSJohn Baldwin main(int argc, char *argv[])
14066bc1e9cdSJohn Baldwin {
14076bc1e9cdSJohn Baldwin 
14086bc1e9cdSJohn Baldwin 	signal(SIGSYS, SIG_IGN);
14096bc1e9cdSJohn Baldwin 	run_tests();
14106bc1e9cdSJohn Baldwin 	return (0);
14116bc1e9cdSJohn Baldwin }
1412