13b0a9131SEnji Cooper /* $NetBSD: t_sem.c,v 1.9 2017/01/16 16:22:22 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*
457718be8SEnji Cooper  * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper  * modification, are permitted provided that the following conditions
957718be8SEnji Cooper  * are met:
1057718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1157718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1257718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1357718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1457718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1557718be8SEnji Cooper  *
1657718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1757718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1857718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1957718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2057718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2157718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2257718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2357718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2457718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2557718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2657718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
2757718be8SEnji Cooper  */
2857718be8SEnji Cooper 
2957718be8SEnji Cooper /*-
3057718be8SEnji Cooper  * Copyright (c)2004 YAMAMOTO Takashi,
3157718be8SEnji Cooper  * All rights reserved.
3257718be8SEnji Cooper  *
3357718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
3457718be8SEnji Cooper  * modification, are permitted provided that the following conditions
3557718be8SEnji Cooper  * are met:
3657718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
3757718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
3857718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
3957718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
4057718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
4157718be8SEnji Cooper  *
4257718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4357718be8SEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4457718be8SEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4557718be8SEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4657718be8SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4757718be8SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4857718be8SEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4957718be8SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5057718be8SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5157718be8SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5257718be8SEnji Cooper  * SUCH DAMAGE.
5357718be8SEnji Cooper  */
5457718be8SEnji Cooper 
5557718be8SEnji Cooper /****************************************************************************
5657718be8SEnji Cooper  *
5757718be8SEnji Cooper  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
5857718be8SEnji Cooper  * All rights reserved.
5957718be8SEnji Cooper  *
6057718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
6157718be8SEnji Cooper  * modification, are permitted provided that the following conditions
6257718be8SEnji Cooper  * are met:
6357718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
6457718be8SEnji Cooper  *    notice(s), this list of conditions and the following disclaimer as
6557718be8SEnji Cooper  *    the first lines of this file unmodified other than the possible
6657718be8SEnji Cooper  *    addition of one or more copyright notices.
6757718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
6857718be8SEnji Cooper  *    notice(s), this list of conditions and the following disclaimer in
6957718be8SEnji Cooper  *    the documentation and/or other materials provided with the
7057718be8SEnji Cooper  *    distribution.
7157718be8SEnji Cooper  *
7257718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
7357718be8SEnji Cooper  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7457718be8SEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7557718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
7657718be8SEnji Cooper  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7757718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7857718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
7957718be8SEnji Cooper  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
8057718be8SEnji Cooper  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
8157718be8SEnji Cooper  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
8257718be8SEnji Cooper  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8357718be8SEnji Cooper  *
8457718be8SEnji Cooper  ****************************************************************************/
8557718be8SEnji Cooper 
8657718be8SEnji Cooper #include <sys/cdefs.h>
8757718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
8857718be8SEnji Cooper  The NetBSD Foundation, inc. All rights reserved.");
893b0a9131SEnji Cooper __RCSID("$NetBSD: t_sem.c,v 1.9 2017/01/16 16:22:22 christos Exp $");
9057718be8SEnji Cooper 
913b0a9131SEnji Cooper #include <sys/time.h>
9257718be8SEnji Cooper #include <errno.h>
9357718be8SEnji Cooper #include <fcntl.h>
9457718be8SEnji Cooper #include <pthread.h>
9557718be8SEnji Cooper #include <semaphore.h>
9657718be8SEnji Cooper #include <signal.h>
9757718be8SEnji Cooper #include <stdio.h>
9857718be8SEnji Cooper #include <stdlib.h>
9957718be8SEnji Cooper #include <string.h>
10057718be8SEnji Cooper #include <unistd.h>
10157718be8SEnji Cooper 
10257718be8SEnji Cooper #include <atf-c.h>
10357718be8SEnji Cooper 
10457718be8SEnji Cooper #include "h_common.h"
10557718be8SEnji Cooper 
10657718be8SEnji Cooper #define NTHREADS 10
10757718be8SEnji Cooper 
10857718be8SEnji Cooper #define _LIBC_R_
10957718be8SEnji Cooper 
11057718be8SEnji Cooper #define SEM_REQUIRE(x) \
11157718be8SEnji Cooper 	ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno))
11257718be8SEnji Cooper 
11357718be8SEnji Cooper static sem_t sem;
11457718be8SEnji Cooper 
11557718be8SEnji Cooper ATF_TC(named);
ATF_TC_HEAD(named,tc)11657718be8SEnji Cooper ATF_TC_HEAD(named, tc)
11757718be8SEnji Cooper {
11857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks named semaphores");
11957718be8SEnji Cooper }
ATF_TC_BODY(named,tc)12057718be8SEnji Cooper ATF_TC_BODY(named, tc)
12157718be8SEnji Cooper {
12257718be8SEnji Cooper 	sem_t *semp;
12357718be8SEnji Cooper 
12457718be8SEnji Cooper 	ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
12557718be8SEnji Cooper 
12657718be8SEnji Cooper 	printf("Test begin\n");
12757718be8SEnji Cooper 
12857718be8SEnji Cooper 	(void) sem_unlink("/foo");
12957718be8SEnji Cooper 	semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0);
13057718be8SEnji Cooper 	ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno));
13157718be8SEnji Cooper 	SEM_REQUIRE(sem_close(semp));
13257718be8SEnji Cooper 	SEM_REQUIRE(sem_unlink("/foo"));
13357718be8SEnji Cooper 
13457718be8SEnji Cooper 	printf("Test end\n");
13557718be8SEnji Cooper }
13657718be8SEnji Cooper 
13757718be8SEnji Cooper ATF_TC(unnamed);
ATF_TC_HEAD(unnamed,tc)13857718be8SEnji Cooper ATF_TC_HEAD(unnamed, tc)
13957718be8SEnji Cooper {
14057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores");
14157718be8SEnji Cooper }
14257718be8SEnji Cooper 
14357718be8SEnji Cooper static void *
entry(void * a_arg)14457718be8SEnji Cooper entry(void * a_arg)
14557718be8SEnji Cooper {
14657718be8SEnji Cooper 	pthread_t self = pthread_self();
14757718be8SEnji Cooper 	sem_t *semp = (sem_t *) a_arg;
14857718be8SEnji Cooper 
14957718be8SEnji Cooper 	printf("Thread %p waiting for semaphore...\n", self);
15057718be8SEnji Cooper 	sem_wait(semp);
15157718be8SEnji Cooper 	printf("Thread %p got semaphore\n", self);
15257718be8SEnji Cooper 
15357718be8SEnji Cooper 	return NULL;
15457718be8SEnji Cooper }
15557718be8SEnji Cooper 
ATF_TC_BODY(unnamed,tc)15657718be8SEnji Cooper ATF_TC_BODY(unnamed, tc)
15757718be8SEnji Cooper {
15857718be8SEnji Cooper 	sem_t sem_a, sem_b;
15957718be8SEnji Cooper 	pthread_t threads[NTHREADS];
16057718be8SEnji Cooper 	unsigned i, j;
16157718be8SEnji Cooper 	int val;
16257718be8SEnji Cooper 
16357718be8SEnji Cooper 	ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
16457718be8SEnji Cooper 
16557718be8SEnji Cooper 	printf("Test begin\n");
16657718be8SEnji Cooper 
16757718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem_b, 0, 0));
16857718be8SEnji Cooper 	SEM_REQUIRE(sem_getvalue(&sem_b, &val));
16957718be8SEnji Cooper 	ATF_REQUIRE_EQ(0, val);
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
17257718be8SEnji Cooper 	SEM_REQUIRE(sem_getvalue(&sem_b, &val));
17357718be8SEnji Cooper 	ATF_REQUIRE_EQ(1, val);
17457718be8SEnji Cooper 
17557718be8SEnji Cooper 	SEM_REQUIRE(sem_wait(&sem_b));
17657718be8SEnji Cooper 	ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1);
17757718be8SEnji Cooper 	ATF_REQUIRE_EQ(errno, EAGAIN);
17857718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
17957718be8SEnji Cooper 	SEM_REQUIRE(sem_trywait(&sem_b));
18057718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
18157718be8SEnji Cooper 	SEM_REQUIRE(sem_wait(&sem_b));
18257718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
18357718be8SEnji Cooper 
18457718be8SEnji Cooper 	SEM_REQUIRE(sem_destroy(&sem_b));
18557718be8SEnji Cooper 
18657718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem_a, 0, 0));
18757718be8SEnji Cooper 
18857718be8SEnji Cooper 	for (j = 0; j < 2; j++) {
18957718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
19057718be8SEnji Cooper 			PTHREAD_REQUIRE(pthread_create(&threads[i], NULL,
19157718be8SEnji Cooper 				entry, (void *) &sem_a));
19257718be8SEnji Cooper 		}
19357718be8SEnji Cooper 
19457718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
19557718be8SEnji Cooper 			usleep(10000);
19657718be8SEnji Cooper 			printf("main loop %u: posting...\n", j+1);
19757718be8SEnji Cooper 			SEM_REQUIRE(sem_post(&sem_a));
19857718be8SEnji Cooper 		}
19957718be8SEnji Cooper 
20057718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
20157718be8SEnji Cooper 			PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
20257718be8SEnji Cooper 		}
20357718be8SEnji Cooper 	}
20457718be8SEnji Cooper 
20557718be8SEnji Cooper 	SEM_REQUIRE(sem_destroy(&sem_a));
20657718be8SEnji Cooper 
20757718be8SEnji Cooper 	printf("Test end\n");
20857718be8SEnji Cooper }
20957718be8SEnji Cooper 
21057718be8SEnji Cooper static void
sighandler(int signo)21157718be8SEnji Cooper sighandler(int signo)
21257718be8SEnji Cooper {
21357718be8SEnji Cooper 	/* printf("signal %d\n", signo); */
21457718be8SEnji Cooper 
21557718be8SEnji Cooper 	ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal");
21657718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem));
21757718be8SEnji Cooper }
21857718be8SEnji Cooper 
21957718be8SEnji Cooper static void
alarm_ms(const int ms)22057718be8SEnji Cooper alarm_ms(const int ms)
22157718be8SEnji Cooper {
22257718be8SEnji Cooper 	struct itimerval timer;
22357718be8SEnji Cooper 	timer.it_interval.tv_sec = 0;
22457718be8SEnji Cooper 	timer.it_interval.tv_usec = 0;
22557718be8SEnji Cooper 	timer.it_value.tv_sec = 0;
22657718be8SEnji Cooper 	timer.it_value.tv_usec = ms * 1000;
22757718be8SEnji Cooper 	ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0);
22857718be8SEnji Cooper }
22957718be8SEnji Cooper 
23057718be8SEnji Cooper static void *
threadfunc(void * arg)23157718be8SEnji Cooper threadfunc(void *arg)
23257718be8SEnji Cooper {
23357718be8SEnji Cooper 	int i, ret;
23457718be8SEnji Cooper 
23557718be8SEnji Cooper 	printf("Entering loop\n");
23657718be8SEnji Cooper 	for (i = 0; i < 500; ) {
23757718be8SEnji Cooper 		if ((i & 1) != 0) {
23857718be8SEnji Cooper 			do {
23957718be8SEnji Cooper 				ret = sem_wait(&sem);
24057718be8SEnji Cooper 			} while (ret == -1 && errno == EINTR);
24157718be8SEnji Cooper 			ATF_REQUIRE(ret == 0);
24257718be8SEnji Cooper 		} else {
24357718be8SEnji Cooper 			ret = sem_trywait(&sem);
24457718be8SEnji Cooper 			if (ret == -1) {
24557718be8SEnji Cooper 				ATF_REQUIRE(errno == EAGAIN);
24657718be8SEnji Cooper 				continue;
24757718be8SEnji Cooper 			}
24857718be8SEnji Cooper 		}
24957718be8SEnji Cooper 		printf("%s: %d\n", __func__, i);
25057718be8SEnji Cooper 		alarm_ms(5);
25157718be8SEnji Cooper 		i++;
25257718be8SEnji Cooper 	}
25357718be8SEnji Cooper 
25457718be8SEnji Cooper 	return NULL;
25557718be8SEnji Cooper }
25657718be8SEnji Cooper 
25757718be8SEnji Cooper static void
before_start_test(const bool use_pthread)25857718be8SEnji Cooper before_start_test(const bool use_pthread)
25957718be8SEnji Cooper {
26057718be8SEnji Cooper 	pthread_t t;
26157718be8SEnji Cooper 
26257718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem, 0, 0));
26357718be8SEnji Cooper 	ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler));
26457718be8SEnji Cooper 
26557718be8SEnji Cooper 	alarm_ms(5);
26657718be8SEnji Cooper 
26757718be8SEnji Cooper 	if (use_pthread) {
26857718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL));
26957718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_join(t, NULL));
27057718be8SEnji Cooper 	} else {
27157718be8SEnji Cooper 		threadfunc(NULL);
27257718be8SEnji Cooper 	}
27357718be8SEnji Cooper }
27457718be8SEnji Cooper 
27557718be8SEnji Cooper ATF_TC(before_start_no_threads);
ATF_TC_HEAD(before_start_no_threads,tc)27657718be8SEnji Cooper ATF_TC_HEAD(before_start_no_threads, tc)
27757718be8SEnji Cooper {
27857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any "
27957718be8SEnji Cooper 	    "thread running");
28057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
28157718be8SEnji Cooper }
ATF_TC_BODY(before_start_no_threads,tc)28257718be8SEnji Cooper ATF_TC_BODY(before_start_no_threads, tc)
28357718be8SEnji Cooper {
28457718be8SEnji Cooper 	before_start_test(false);
28557718be8SEnji Cooper }
28657718be8SEnji Cooper 
28757718be8SEnji Cooper ATF_TC(before_start_one_thread);
ATF_TC_HEAD(before_start_one_thread,tc)28857718be8SEnji Cooper ATF_TC_HEAD(before_start_one_thread, tc)
28957718be8SEnji Cooper {
29057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks using semaphores before "
29157718be8SEnji Cooper 	    "starting one thread");
29257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
29357718be8SEnji Cooper }
ATF_TC_BODY(before_start_one_thread,tc)29457718be8SEnji Cooper ATF_TC_BODY(before_start_one_thread, tc)
29557718be8SEnji Cooper {
29657718be8SEnji Cooper 	before_start_test(true);
29757718be8SEnji Cooper }
29857718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)29957718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
30057718be8SEnji Cooper {
30157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, named);
30257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, unnamed);
30357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, before_start_no_threads);
30457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, before_start_one_thread);
30557718be8SEnji Cooper 
30657718be8SEnji Cooper 	return atf_no_error();
30757718be8SEnji Cooper }
308