1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_sem.c,v 1.8 2014/11/04 00:20:19 justin Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc * All rights reserved.
611be35a1SLionel Sambuc *
711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc * are met:
1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc *
1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1711be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1811be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1911be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2011be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2111be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2211be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2311be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2411be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2511be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2611be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
2711be35a1SLionel Sambuc */
2811be35a1SLionel Sambuc
2911be35a1SLionel Sambuc /*-
3011be35a1SLionel Sambuc * Copyright (c)2004 YAMAMOTO Takashi,
3111be35a1SLionel Sambuc * All rights reserved.
3211be35a1SLionel Sambuc *
3311be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
3411be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
3511be35a1SLionel Sambuc * are met:
3611be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
3711be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
3811be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
3911be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
4011be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
4111be35a1SLionel Sambuc *
4211be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4311be35a1SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4411be35a1SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4511be35a1SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4611be35a1SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4711be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4811be35a1SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4911be35a1SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5011be35a1SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5111be35a1SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5211be35a1SLionel Sambuc * SUCH DAMAGE.
5311be35a1SLionel Sambuc */
5411be35a1SLionel Sambuc
5511be35a1SLionel Sambuc /****************************************************************************
5611be35a1SLionel Sambuc *
5711be35a1SLionel Sambuc * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
5811be35a1SLionel Sambuc * All rights reserved.
5911be35a1SLionel Sambuc *
6011be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
6111be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
6211be35a1SLionel Sambuc * are met:
6311be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
6411be35a1SLionel Sambuc * notice(s), this list of conditions and the following disclaimer as
6511be35a1SLionel Sambuc * the first lines of this file unmodified other than the possible
6611be35a1SLionel Sambuc * addition of one or more copyright notices.
6711be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
6811be35a1SLionel Sambuc * notice(s), this list of conditions and the following disclaimer in
6911be35a1SLionel Sambuc * the documentation and/or other materials provided with the
7011be35a1SLionel Sambuc * distribution.
7111be35a1SLionel Sambuc *
7211be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
7311be35a1SLionel Sambuc * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7411be35a1SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7511be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
7611be35a1SLionel Sambuc * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7711be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7811be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
7911be35a1SLionel Sambuc * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
8011be35a1SLionel Sambuc * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
8111be35a1SLionel Sambuc * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
8211be35a1SLionel Sambuc * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8311be35a1SLionel Sambuc *
8411be35a1SLionel Sambuc ****************************************************************************/
8511be35a1SLionel Sambuc
8611be35a1SLionel Sambuc #include <sys/cdefs.h>
8711be35a1SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
8811be35a1SLionel Sambuc The NetBSD Foundation, inc. All rights reserved.");
89*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: t_sem.c,v 1.8 2014/11/04 00:20:19 justin Exp $");
9011be35a1SLionel Sambuc
9111be35a1SLionel Sambuc #include <errno.h>
9211be35a1SLionel Sambuc #include <fcntl.h>
9311be35a1SLionel Sambuc #include <pthread.h>
9411be35a1SLionel Sambuc #include <semaphore.h>
9511be35a1SLionel Sambuc #include <signal.h>
9611be35a1SLionel Sambuc #include <stdio.h>
9711be35a1SLionel Sambuc #include <stdlib.h>
9811be35a1SLionel Sambuc #include <string.h>
9911be35a1SLionel Sambuc #include <unistd.h>
10011be35a1SLionel Sambuc
10111be35a1SLionel Sambuc #include <atf-c.h>
10211be35a1SLionel Sambuc
10311be35a1SLionel Sambuc #include "h_common.h"
10411be35a1SLionel Sambuc
10511be35a1SLionel Sambuc #define NTHREADS 10
10611be35a1SLionel Sambuc
10711be35a1SLionel Sambuc #define _LIBC_R_
10811be35a1SLionel Sambuc
10911be35a1SLionel Sambuc #define SEM_REQUIRE(x) \
11011be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno))
11111be35a1SLionel Sambuc
11211be35a1SLionel Sambuc static sem_t sem;
11311be35a1SLionel Sambuc
11411be35a1SLionel Sambuc ATF_TC(named);
ATF_TC_HEAD(named,tc)11511be35a1SLionel Sambuc ATF_TC_HEAD(named, tc)
11611be35a1SLionel Sambuc {
11711be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks named semaphores");
11811be35a1SLionel Sambuc }
ATF_TC_BODY(named,tc)11911be35a1SLionel Sambuc ATF_TC_BODY(named, tc)
12011be35a1SLionel Sambuc {
12111be35a1SLionel Sambuc sem_t *semp;
12211be35a1SLionel Sambuc
12311be35a1SLionel Sambuc ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
12411be35a1SLionel Sambuc
12511be35a1SLionel Sambuc printf("Test begin\n");
12611be35a1SLionel Sambuc
12711be35a1SLionel Sambuc (void) sem_unlink("/foo");
12811be35a1SLionel Sambuc semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0);
12911be35a1SLionel Sambuc ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno));
13011be35a1SLionel Sambuc SEM_REQUIRE(sem_close(semp));
13111be35a1SLionel Sambuc SEM_REQUIRE(sem_unlink("/foo"));
13211be35a1SLionel Sambuc
13311be35a1SLionel Sambuc printf("Test end\n");
13411be35a1SLionel Sambuc }
13511be35a1SLionel Sambuc
13611be35a1SLionel Sambuc ATF_TC(unnamed);
ATF_TC_HEAD(unnamed,tc)13711be35a1SLionel Sambuc ATF_TC_HEAD(unnamed, tc)
13811be35a1SLionel Sambuc {
13911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores");
14011be35a1SLionel Sambuc }
14111be35a1SLionel Sambuc
14211be35a1SLionel Sambuc static void *
entry(void * a_arg)14311be35a1SLionel Sambuc entry(void * a_arg)
14411be35a1SLionel Sambuc {
14511be35a1SLionel Sambuc pthread_t self = pthread_self();
14611be35a1SLionel Sambuc sem_t *semp = (sem_t *) a_arg;
14711be35a1SLionel Sambuc
14811be35a1SLionel Sambuc printf("Thread %p waiting for semaphore...\n", self);
14911be35a1SLionel Sambuc sem_wait(semp);
15011be35a1SLionel Sambuc printf("Thread %p got semaphore\n", self);
15111be35a1SLionel Sambuc
15211be35a1SLionel Sambuc return NULL;
15311be35a1SLionel Sambuc }
15411be35a1SLionel Sambuc
ATF_TC_BODY(unnamed,tc)15511be35a1SLionel Sambuc ATF_TC_BODY(unnamed, tc)
15611be35a1SLionel Sambuc {
15711be35a1SLionel Sambuc sem_t sem_a, sem_b;
15811be35a1SLionel Sambuc pthread_t threads[NTHREADS];
15911be35a1SLionel Sambuc unsigned i, j;
16011be35a1SLionel Sambuc int val;
16111be35a1SLionel Sambuc
16211be35a1SLionel Sambuc ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
16311be35a1SLionel Sambuc
16411be35a1SLionel Sambuc printf("Test begin\n");
16511be35a1SLionel Sambuc
16611be35a1SLionel Sambuc SEM_REQUIRE(sem_init(&sem_b, 0, 0));
16711be35a1SLionel Sambuc SEM_REQUIRE(sem_getvalue(&sem_b, &val));
16811be35a1SLionel Sambuc ATF_REQUIRE_EQ(0, val);
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem_b));
17111be35a1SLionel Sambuc SEM_REQUIRE(sem_getvalue(&sem_b, &val));
17211be35a1SLionel Sambuc ATF_REQUIRE_EQ(1, val);
17311be35a1SLionel Sambuc
17411be35a1SLionel Sambuc SEM_REQUIRE(sem_wait(&sem_b));
17511be35a1SLionel Sambuc ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1);
17611be35a1SLionel Sambuc ATF_REQUIRE_EQ(errno, EAGAIN);
17711be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem_b));
17811be35a1SLionel Sambuc SEM_REQUIRE(sem_trywait(&sem_b));
17911be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem_b));
18011be35a1SLionel Sambuc SEM_REQUIRE(sem_wait(&sem_b));
18111be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem_b));
18211be35a1SLionel Sambuc
18311be35a1SLionel Sambuc SEM_REQUIRE(sem_destroy(&sem_b));
18411be35a1SLionel Sambuc
18511be35a1SLionel Sambuc SEM_REQUIRE(sem_init(&sem_a, 0, 0));
18611be35a1SLionel Sambuc
18711be35a1SLionel Sambuc for (j = 0; j < 2; j++) {
18811be35a1SLionel Sambuc for (i = 0; i < NTHREADS; i++) {
18911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&threads[i], NULL,
19011be35a1SLionel Sambuc entry, (void *) &sem_a));
19111be35a1SLionel Sambuc }
19211be35a1SLionel Sambuc
19311be35a1SLionel Sambuc for (i = 0; i < NTHREADS; i++) {
19411be35a1SLionel Sambuc usleep(10000);
19511be35a1SLionel Sambuc printf("main loop %u: posting...\n", j+1);
19611be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem_a));
19711be35a1SLionel Sambuc }
19811be35a1SLionel Sambuc
19911be35a1SLionel Sambuc for (i = 0; i < NTHREADS; i++) {
20011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
20111be35a1SLionel Sambuc }
20211be35a1SLionel Sambuc }
20311be35a1SLionel Sambuc
20411be35a1SLionel Sambuc SEM_REQUIRE(sem_destroy(&sem_a));
20511be35a1SLionel Sambuc
20611be35a1SLionel Sambuc printf("Test end\n");
20711be35a1SLionel Sambuc }
20811be35a1SLionel Sambuc
20911be35a1SLionel Sambuc static void
sighandler(int signo)21011be35a1SLionel Sambuc sighandler(int signo)
21111be35a1SLionel Sambuc {
21211be35a1SLionel Sambuc /* printf("signal %d\n", signo); */
21311be35a1SLionel Sambuc
21411be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal");
21511be35a1SLionel Sambuc SEM_REQUIRE(sem_post(&sem));
21611be35a1SLionel Sambuc }
21711be35a1SLionel Sambuc
21811be35a1SLionel Sambuc static void
alarm_ms(const int ms)21911be35a1SLionel Sambuc alarm_ms(const int ms)
22011be35a1SLionel Sambuc {
22111be35a1SLionel Sambuc struct itimerval timer;
22211be35a1SLionel Sambuc timer.it_interval.tv_sec = 0;
22311be35a1SLionel Sambuc timer.it_interval.tv_usec = 0;
22411be35a1SLionel Sambuc timer.it_value.tv_sec = 0;
22511be35a1SLionel Sambuc timer.it_value.tv_usec = ms * 1000;
22611be35a1SLionel Sambuc ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0);
22711be35a1SLionel Sambuc }
22811be35a1SLionel Sambuc
22911be35a1SLionel Sambuc static void *
threadfunc(void * arg)23011be35a1SLionel Sambuc threadfunc(void *arg)
23111be35a1SLionel Sambuc {
23211be35a1SLionel Sambuc int i, ret;
23311be35a1SLionel Sambuc
23411be35a1SLionel Sambuc printf("Entering loop\n");
23511be35a1SLionel Sambuc for (i = 0; i < 500; ) {
23611be35a1SLionel Sambuc if ((i & 1) != 0) {
23711be35a1SLionel Sambuc do {
23811be35a1SLionel Sambuc ret = sem_wait(&sem);
23911be35a1SLionel Sambuc } while (ret == -1 && errno == EINTR);
24011be35a1SLionel Sambuc ATF_REQUIRE(ret == 0);
24111be35a1SLionel Sambuc } else {
24211be35a1SLionel Sambuc ret = sem_trywait(&sem);
24311be35a1SLionel Sambuc if (ret == -1) {
24411be35a1SLionel Sambuc ATF_REQUIRE(errno == EAGAIN);
24511be35a1SLionel Sambuc continue;
24611be35a1SLionel Sambuc }
24711be35a1SLionel Sambuc }
24811be35a1SLionel Sambuc printf("%s: %d\n", __func__, i);
24911be35a1SLionel Sambuc alarm_ms(5);
25011be35a1SLionel Sambuc i++;
25111be35a1SLionel Sambuc }
25211be35a1SLionel Sambuc
25311be35a1SLionel Sambuc return NULL;
25411be35a1SLionel Sambuc }
25511be35a1SLionel Sambuc
25611be35a1SLionel Sambuc static void
before_start_test(const bool use_pthread)25711be35a1SLionel Sambuc before_start_test(const bool use_pthread)
25811be35a1SLionel Sambuc {
25911be35a1SLionel Sambuc pthread_t t;
26011be35a1SLionel Sambuc
26111be35a1SLionel Sambuc SEM_REQUIRE(sem_init(&sem, 0, 0));
26211be35a1SLionel Sambuc ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler));
26311be35a1SLionel Sambuc
26411be35a1SLionel Sambuc alarm_ms(5);
26511be35a1SLionel Sambuc
26611be35a1SLionel Sambuc if (use_pthread) {
26711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL));
26811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(t, NULL));
26911be35a1SLionel Sambuc } else {
27011be35a1SLionel Sambuc threadfunc(NULL);
27111be35a1SLionel Sambuc }
27211be35a1SLionel Sambuc }
27311be35a1SLionel Sambuc
27411be35a1SLionel Sambuc ATF_TC(before_start_no_threads);
ATF_TC_HEAD(before_start_no_threads,tc)27511be35a1SLionel Sambuc ATF_TC_HEAD(before_start_no_threads, tc)
27611be35a1SLionel Sambuc {
27711be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any "
27811be35a1SLionel Sambuc "thread running");
27911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "timeout", "40");
28011be35a1SLionel Sambuc }
ATF_TC_BODY(before_start_no_threads,tc)28111be35a1SLionel Sambuc ATF_TC_BODY(before_start_no_threads, tc)
28211be35a1SLionel Sambuc {
28311be35a1SLionel Sambuc before_start_test(false);
28411be35a1SLionel Sambuc }
28511be35a1SLionel Sambuc
28611be35a1SLionel Sambuc ATF_TC(before_start_one_thread);
ATF_TC_HEAD(before_start_one_thread,tc)28711be35a1SLionel Sambuc ATF_TC_HEAD(before_start_one_thread, tc)
28811be35a1SLionel Sambuc {
28911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks using semaphores before "
29011be35a1SLionel Sambuc "starting one thread");
29111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "timeout", "40");
29211be35a1SLionel Sambuc }
ATF_TC_BODY(before_start_one_thread,tc)29311be35a1SLionel Sambuc ATF_TC_BODY(before_start_one_thread, tc)
29411be35a1SLionel Sambuc {
29511be35a1SLionel Sambuc before_start_test(true);
29611be35a1SLionel Sambuc }
29711be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)29811be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
29911be35a1SLionel Sambuc {
30011be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, named);
30111be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, unnamed);
30211be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, before_start_no_threads);
30311be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, before_start_one_thread);
30411be35a1SLionel Sambuc
30511be35a1SLionel Sambuc return atf_no_error();
30611be35a1SLionel Sambuc }
307