xref: /freebsd/contrib/netbsd-tests/lib/libpthread/t_sem.c (revision 3b0a9131e6cb4ada420cbfc4e2d89a04ca7ad384)
1*3b0a9131SEnji 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.");
89*3b0a9131SEnji Cooper __RCSID("$NetBSD: t_sem.c,v 1.9 2017/01/16 16:22:22 christos Exp $");
9057718be8SEnji Cooper 
91*3b0a9131SEnji 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 
115a20294deSEnji Cooper #ifdef __FreeBSD__
116a20294deSEnji Cooper #include <sys/time.h>
117a20294deSEnji Cooper #endif
118a20294deSEnji Cooper 
11957718be8SEnji Cooper ATF_TC(named);
12057718be8SEnji Cooper ATF_TC_HEAD(named, tc)
12157718be8SEnji Cooper {
12257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks named semaphores");
12357718be8SEnji Cooper }
12457718be8SEnji Cooper ATF_TC_BODY(named, tc)
12557718be8SEnji Cooper {
12657718be8SEnji Cooper 	sem_t *semp;
12757718be8SEnji Cooper 
12857718be8SEnji Cooper 	ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
12957718be8SEnji Cooper 
13057718be8SEnji Cooper 	printf("Test begin\n");
13157718be8SEnji Cooper 
13257718be8SEnji Cooper 	(void) sem_unlink("/foo");
13357718be8SEnji Cooper 	semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0);
13457718be8SEnji Cooper 	ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno));
13557718be8SEnji Cooper 	SEM_REQUIRE(sem_close(semp));
13657718be8SEnji Cooper 	SEM_REQUIRE(sem_unlink("/foo"));
13757718be8SEnji Cooper 
13857718be8SEnji Cooper 	printf("Test end\n");
13957718be8SEnji Cooper }
14057718be8SEnji Cooper 
14157718be8SEnji Cooper ATF_TC(unnamed);
14257718be8SEnji Cooper ATF_TC_HEAD(unnamed, tc)
14357718be8SEnji Cooper {
14457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores");
14557718be8SEnji Cooper }
14657718be8SEnji Cooper 
14757718be8SEnji Cooper static void *
14857718be8SEnji Cooper entry(void * a_arg)
14957718be8SEnji Cooper {
15057718be8SEnji Cooper 	pthread_t self = pthread_self();
15157718be8SEnji Cooper 	sem_t *semp = (sem_t *) a_arg;
15257718be8SEnji Cooper 
15357718be8SEnji Cooper 	printf("Thread %p waiting for semaphore...\n", self);
15457718be8SEnji Cooper 	sem_wait(semp);
15557718be8SEnji Cooper 	printf("Thread %p got semaphore\n", self);
15657718be8SEnji Cooper 
15757718be8SEnji Cooper 	return NULL;
15857718be8SEnji Cooper }
15957718be8SEnji Cooper 
16057718be8SEnji Cooper ATF_TC_BODY(unnamed, tc)
16157718be8SEnji Cooper {
16257718be8SEnji Cooper 	sem_t sem_a, sem_b;
16357718be8SEnji Cooper 	pthread_t threads[NTHREADS];
16457718be8SEnji Cooper 	unsigned i, j;
16557718be8SEnji Cooper 	int val;
16657718be8SEnji Cooper 
16757718be8SEnji Cooper 	ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
16857718be8SEnji Cooper 
16957718be8SEnji Cooper 	printf("Test begin\n");
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem_b, 0, 0));
17257718be8SEnji Cooper 	SEM_REQUIRE(sem_getvalue(&sem_b, &val));
17357718be8SEnji Cooper 	ATF_REQUIRE_EQ(0, val);
17457718be8SEnji Cooper 
17557718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
17657718be8SEnji Cooper 	SEM_REQUIRE(sem_getvalue(&sem_b, &val));
17757718be8SEnji Cooper 	ATF_REQUIRE_EQ(1, val);
17857718be8SEnji Cooper 
17957718be8SEnji Cooper 	SEM_REQUIRE(sem_wait(&sem_b));
18057718be8SEnji Cooper 	ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1);
18157718be8SEnji Cooper 	ATF_REQUIRE_EQ(errno, EAGAIN);
18257718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
18357718be8SEnji Cooper 	SEM_REQUIRE(sem_trywait(&sem_b));
18457718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
18557718be8SEnji Cooper 	SEM_REQUIRE(sem_wait(&sem_b));
18657718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem_b));
18757718be8SEnji Cooper 
18857718be8SEnji Cooper 	SEM_REQUIRE(sem_destroy(&sem_b));
18957718be8SEnji Cooper 
19057718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem_a, 0, 0));
19157718be8SEnji Cooper 
19257718be8SEnji Cooper 	for (j = 0; j < 2; j++) {
19357718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
19457718be8SEnji Cooper 			PTHREAD_REQUIRE(pthread_create(&threads[i], NULL,
19557718be8SEnji Cooper 				entry, (void *) &sem_a));
19657718be8SEnji Cooper 		}
19757718be8SEnji Cooper 
19857718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
19957718be8SEnji Cooper 			usleep(10000);
20057718be8SEnji Cooper 			printf("main loop %u: posting...\n", j+1);
20157718be8SEnji Cooper 			SEM_REQUIRE(sem_post(&sem_a));
20257718be8SEnji Cooper 		}
20357718be8SEnji Cooper 
20457718be8SEnji Cooper 		for (i = 0; i < NTHREADS; i++) {
20557718be8SEnji Cooper 			PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
20657718be8SEnji Cooper 		}
20757718be8SEnji Cooper 	}
20857718be8SEnji Cooper 
20957718be8SEnji Cooper 	SEM_REQUIRE(sem_destroy(&sem_a));
21057718be8SEnji Cooper 
21157718be8SEnji Cooper 	printf("Test end\n");
21257718be8SEnji Cooper }
21357718be8SEnji Cooper 
21457718be8SEnji Cooper static void
21557718be8SEnji Cooper sighandler(int signo)
21657718be8SEnji Cooper {
21757718be8SEnji Cooper 	/* printf("signal %d\n", signo); */
21857718be8SEnji Cooper 
21957718be8SEnji Cooper 	ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal");
22057718be8SEnji Cooper 	SEM_REQUIRE(sem_post(&sem));
22157718be8SEnji Cooper }
22257718be8SEnji Cooper 
22357718be8SEnji Cooper static void
22457718be8SEnji Cooper alarm_ms(const int ms)
22557718be8SEnji Cooper {
22657718be8SEnji Cooper 	struct itimerval timer;
22757718be8SEnji Cooper 	timer.it_interval.tv_sec = 0;
22857718be8SEnji Cooper 	timer.it_interval.tv_usec = 0;
22957718be8SEnji Cooper 	timer.it_value.tv_sec = 0;
23057718be8SEnji Cooper 	timer.it_value.tv_usec = ms * 1000;
23157718be8SEnji Cooper 	ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0);
23257718be8SEnji Cooper }
23357718be8SEnji Cooper 
23457718be8SEnji Cooper static void *
23557718be8SEnji Cooper threadfunc(void *arg)
23657718be8SEnji Cooper {
23757718be8SEnji Cooper 	int i, ret;
23857718be8SEnji Cooper 
23957718be8SEnji Cooper 	printf("Entering loop\n");
24057718be8SEnji Cooper 	for (i = 0; i < 500; ) {
24157718be8SEnji Cooper 		if ((i & 1) != 0) {
24257718be8SEnji Cooper 			do {
24357718be8SEnji Cooper 				ret = sem_wait(&sem);
24457718be8SEnji Cooper 			} while (ret == -1 && errno == EINTR);
24557718be8SEnji Cooper 			ATF_REQUIRE(ret == 0);
24657718be8SEnji Cooper 		} else {
24757718be8SEnji Cooper 			ret = sem_trywait(&sem);
24857718be8SEnji Cooper 			if (ret == -1) {
24957718be8SEnji Cooper 				ATF_REQUIRE(errno == EAGAIN);
25057718be8SEnji Cooper 				continue;
25157718be8SEnji Cooper 			}
25257718be8SEnji Cooper 		}
25357718be8SEnji Cooper 		printf("%s: %d\n", __func__, i);
25457718be8SEnji Cooper 		alarm_ms(5);
25557718be8SEnji Cooper 		i++;
25657718be8SEnji Cooper 	}
25757718be8SEnji Cooper 
25857718be8SEnji Cooper 	return NULL;
25957718be8SEnji Cooper }
26057718be8SEnji Cooper 
26157718be8SEnji Cooper static void
26257718be8SEnji Cooper before_start_test(const bool use_pthread)
26357718be8SEnji Cooper {
26457718be8SEnji Cooper 	pthread_t t;
26557718be8SEnji Cooper 
26657718be8SEnji Cooper 	SEM_REQUIRE(sem_init(&sem, 0, 0));
26757718be8SEnji Cooper 	ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler));
26857718be8SEnji Cooper 
26957718be8SEnji Cooper 	alarm_ms(5);
27057718be8SEnji Cooper 
27157718be8SEnji Cooper 	if (use_pthread) {
27257718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL));
27357718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_join(t, NULL));
27457718be8SEnji Cooper 	} else {
27557718be8SEnji Cooper 		threadfunc(NULL);
27657718be8SEnji Cooper 	}
27757718be8SEnji Cooper }
27857718be8SEnji Cooper 
27957718be8SEnji Cooper ATF_TC(before_start_no_threads);
28057718be8SEnji Cooper ATF_TC_HEAD(before_start_no_threads, tc)
28157718be8SEnji Cooper {
28257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any "
28357718be8SEnji Cooper 	    "thread running");
28457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
28557718be8SEnji Cooper }
28657718be8SEnji Cooper ATF_TC_BODY(before_start_no_threads, tc)
28757718be8SEnji Cooper {
28857718be8SEnji Cooper 	before_start_test(false);
28957718be8SEnji Cooper }
29057718be8SEnji Cooper 
29157718be8SEnji Cooper ATF_TC(before_start_one_thread);
29257718be8SEnji Cooper ATF_TC_HEAD(before_start_one_thread, tc)
29357718be8SEnji Cooper {
29457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks using semaphores before "
29557718be8SEnji Cooper 	    "starting one thread");
29657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
29757718be8SEnji Cooper }
29857718be8SEnji Cooper ATF_TC_BODY(before_start_one_thread, tc)
29957718be8SEnji Cooper {
30057718be8SEnji Cooper 	before_start_test(true);
30157718be8SEnji Cooper }
30257718be8SEnji Cooper 
30357718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
30457718be8SEnji Cooper {
30557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, named);
30657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, unnamed);
30757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, before_start_no_threads);
30857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, before_start_one_thread);
30957718be8SEnji Cooper 
31057718be8SEnji Cooper 	return atf_no_error();
31157718be8SEnji Cooper }
312