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