1*17284898Schristos /* $NetBSD: t_sem.c,v 1.9 2017/01/16 16:22:22 christos Exp $ */
2ac555471Sjmmv
3ac555471Sjmmv /*
4ac555471Sjmmv * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
5ac555471Sjmmv * All rights reserved.
6ac555471Sjmmv *
7ac555471Sjmmv * Redistribution and use in source and binary forms, with or without
8ac555471Sjmmv * modification, are permitted provided that the following conditions
9ac555471Sjmmv * are met:
10ac555471Sjmmv * 1. Redistributions of source code must retain the above copyright
11ac555471Sjmmv * notice, this list of conditions and the following disclaimer.
12ac555471Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
13ac555471Sjmmv * notice, this list of conditions and the following disclaimer in the
14ac555471Sjmmv * documentation and/or other materials provided with the distribution.
15ac555471Sjmmv *
16ac555471Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17ac555471Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18ac555471Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ac555471Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20ac555471Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21ac555471Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22ac555471Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23ac555471Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24ac555471Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ac555471Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ac555471Sjmmv * POSSIBILITY OF SUCH DAMAGE.
27ac555471Sjmmv */
28ac555471Sjmmv
29ac555471Sjmmv /*-
30ac555471Sjmmv * Copyright (c)2004 YAMAMOTO Takashi,
31ac555471Sjmmv * All rights reserved.
32ac555471Sjmmv *
33ac555471Sjmmv * Redistribution and use in source and binary forms, with or without
34ac555471Sjmmv * modification, are permitted provided that the following conditions
35ac555471Sjmmv * are met:
36ac555471Sjmmv * 1. Redistributions of source code must retain the above copyright
37ac555471Sjmmv * notice, this list of conditions and the following disclaimer.
38ac555471Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
39ac555471Sjmmv * notice, this list of conditions and the following disclaimer in the
40ac555471Sjmmv * documentation and/or other materials provided with the distribution.
41ac555471Sjmmv *
42ac555471Sjmmv * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43ac555471Sjmmv * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44ac555471Sjmmv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45ac555471Sjmmv * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46ac555471Sjmmv * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47ac555471Sjmmv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48ac555471Sjmmv * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49ac555471Sjmmv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50ac555471Sjmmv * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51ac555471Sjmmv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52ac555471Sjmmv * SUCH DAMAGE.
53ac555471Sjmmv */
54ac555471Sjmmv
55ac555471Sjmmv /****************************************************************************
56ac555471Sjmmv *
57ac555471Sjmmv * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
58ac555471Sjmmv * All rights reserved.
59ac555471Sjmmv *
60ac555471Sjmmv * Redistribution and use in source and binary forms, with or without
61ac555471Sjmmv * modification, are permitted provided that the following conditions
62ac555471Sjmmv * are met:
63ac555471Sjmmv * 1. Redistributions of source code must retain the above copyright
64ac555471Sjmmv * notice(s), this list of conditions and the following disclaimer as
65ac555471Sjmmv * the first lines of this file unmodified other than the possible
66ac555471Sjmmv * addition of one or more copyright notices.
67ac555471Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
68ac555471Sjmmv * notice(s), this list of conditions and the following disclaimer in
69ac555471Sjmmv * the documentation and/or other materials provided with the
70ac555471Sjmmv * distribution.
71ac555471Sjmmv *
72ac555471Sjmmv * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
73ac555471Sjmmv * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74ac555471Sjmmv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
75ac555471Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
76ac555471Sjmmv * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
77ac555471Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
78ac555471Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
79ac555471Sjmmv * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
80ac555471Sjmmv * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
81ac555471Sjmmv * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
82ac555471Sjmmv * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
83ac555471Sjmmv *
84ac555471Sjmmv ****************************************************************************/
85ac555471Sjmmv
86ac555471Sjmmv #include <sys/cdefs.h>
87ac555471Sjmmv __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
88ac555471Sjmmv The NetBSD Foundation, inc. All rights reserved.");
89*17284898Schristos __RCSID("$NetBSD: t_sem.c,v 1.9 2017/01/16 16:22:22 christos Exp $");
90ac555471Sjmmv
91*17284898Schristos #include <sys/time.h>
92ac555471Sjmmv #include <errno.h>
93ac555471Sjmmv #include <fcntl.h>
94ac555471Sjmmv #include <pthread.h>
95ac555471Sjmmv #include <semaphore.h>
96ac555471Sjmmv #include <signal.h>
97ac555471Sjmmv #include <stdio.h>
98ac555471Sjmmv #include <stdlib.h>
99ac555471Sjmmv #include <string.h>
100ac555471Sjmmv #include <unistd.h>
101ac555471Sjmmv
102ac555471Sjmmv #include <atf-c.h>
103ac555471Sjmmv
104ac555471Sjmmv #include "h_common.h"
105ac555471Sjmmv
106ac555471Sjmmv #define NTHREADS 10
107ac555471Sjmmv
108ac555471Sjmmv #define _LIBC_R_
109ac555471Sjmmv
110ac555471Sjmmv #define SEM_REQUIRE(x) \
111ac555471Sjmmv ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno))
112ac555471Sjmmv
113ac555471Sjmmv static sem_t sem;
114ac555471Sjmmv
115ac555471Sjmmv ATF_TC(named);
ATF_TC_HEAD(named,tc)116ac555471Sjmmv ATF_TC_HEAD(named, tc)
117ac555471Sjmmv {
118ac555471Sjmmv atf_tc_set_md_var(tc, "descr", "Checks named semaphores");
119ac555471Sjmmv }
ATF_TC_BODY(named,tc)120ac555471Sjmmv ATF_TC_BODY(named, tc)
121ac555471Sjmmv {
1220f10aa9dSchristos sem_t *semp;
123ac555471Sjmmv
124ac555471Sjmmv ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
125ac555471Sjmmv
126ac555471Sjmmv printf("Test begin\n");
127ac555471Sjmmv
128ac555471Sjmmv (void) sem_unlink("/foo");
1290f10aa9dSchristos semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0);
1300f10aa9dSchristos ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno));
1310f10aa9dSchristos SEM_REQUIRE(sem_close(semp));
132ac555471Sjmmv SEM_REQUIRE(sem_unlink("/foo"));
133ac555471Sjmmv
134ac555471Sjmmv printf("Test end\n");
135ac555471Sjmmv }
136ac555471Sjmmv
137ac555471Sjmmv ATF_TC(unnamed);
ATF_TC_HEAD(unnamed,tc)138ac555471Sjmmv ATF_TC_HEAD(unnamed, tc)
139ac555471Sjmmv {
140ac555471Sjmmv atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores");
141ac555471Sjmmv }
142ac555471Sjmmv
143ac555471Sjmmv static void *
entry(void * a_arg)144ac555471Sjmmv entry(void * a_arg)
145ac555471Sjmmv {
146ac555471Sjmmv pthread_t self = pthread_self();
1470f10aa9dSchristos sem_t *semp = (sem_t *) a_arg;
148ac555471Sjmmv
149ac555471Sjmmv printf("Thread %p waiting for semaphore...\n", self);
1500f10aa9dSchristos sem_wait(semp);
151ac555471Sjmmv printf("Thread %p got semaphore\n", self);
152ac555471Sjmmv
153ac555471Sjmmv return NULL;
154ac555471Sjmmv }
155ac555471Sjmmv
ATF_TC_BODY(unnamed,tc)156ac555471Sjmmv ATF_TC_BODY(unnamed, tc)
157ac555471Sjmmv {
158ac555471Sjmmv sem_t sem_a, sem_b;
159ac555471Sjmmv pthread_t threads[NTHREADS];
160ac555471Sjmmv unsigned i, j;
161ac555471Sjmmv int val;
162ac555471Sjmmv
163ac555471Sjmmv ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
164ac555471Sjmmv
165ac555471Sjmmv printf("Test begin\n");
166ac555471Sjmmv
167ac555471Sjmmv SEM_REQUIRE(sem_init(&sem_b, 0, 0));
168ac555471Sjmmv SEM_REQUIRE(sem_getvalue(&sem_b, &val));
169ac555471Sjmmv ATF_REQUIRE_EQ(0, val);
170ac555471Sjmmv
171ac555471Sjmmv SEM_REQUIRE(sem_post(&sem_b));
172ac555471Sjmmv SEM_REQUIRE(sem_getvalue(&sem_b, &val));
173ac555471Sjmmv ATF_REQUIRE_EQ(1, val);
174ac555471Sjmmv
175ac555471Sjmmv SEM_REQUIRE(sem_wait(&sem_b));
176ac555471Sjmmv ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1);
177ac555471Sjmmv ATF_REQUIRE_EQ(errno, EAGAIN);
178ac555471Sjmmv SEM_REQUIRE(sem_post(&sem_b));
179ac555471Sjmmv SEM_REQUIRE(sem_trywait(&sem_b));
180ac555471Sjmmv SEM_REQUIRE(sem_post(&sem_b));
181ac555471Sjmmv SEM_REQUIRE(sem_wait(&sem_b));
182ac555471Sjmmv SEM_REQUIRE(sem_post(&sem_b));
183ac555471Sjmmv
184ac555471Sjmmv SEM_REQUIRE(sem_destroy(&sem_b));
185ac555471Sjmmv
186ac555471Sjmmv SEM_REQUIRE(sem_init(&sem_a, 0, 0));
187ac555471Sjmmv
188ac555471Sjmmv for (j = 0; j < 2; j++) {
189ac555471Sjmmv for (i = 0; i < NTHREADS; i++) {
190ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&threads[i], NULL,
191ac555471Sjmmv entry, (void *) &sem_a));
192ac555471Sjmmv }
193ac555471Sjmmv
194ac555471Sjmmv for (i = 0; i < NTHREADS; i++) {
195510b2ec7Spooka usleep(10000);
196ac555471Sjmmv printf("main loop %u: posting...\n", j+1);
197ac555471Sjmmv SEM_REQUIRE(sem_post(&sem_a));
198ac555471Sjmmv }
199ac555471Sjmmv
200ac555471Sjmmv for (i = 0; i < NTHREADS; i++) {
201ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
202ac555471Sjmmv }
203ac555471Sjmmv }
204ac555471Sjmmv
205ac555471Sjmmv SEM_REQUIRE(sem_destroy(&sem_a));
206ac555471Sjmmv
207ac555471Sjmmv printf("Test end\n");
208ac555471Sjmmv }
209ac555471Sjmmv
210ac555471Sjmmv static void
sighandler(int signo)211ac555471Sjmmv sighandler(int signo)
212ac555471Sjmmv {
213ac555471Sjmmv /* printf("signal %d\n", signo); */
214ac555471Sjmmv
215ac555471Sjmmv ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal");
216ac555471Sjmmv SEM_REQUIRE(sem_post(&sem));
217ac555471Sjmmv }
218ac555471Sjmmv
21928cce38fSjmmv static void
alarm_ms(const int ms)22028cce38fSjmmv alarm_ms(const int ms)
22128cce38fSjmmv {
22228cce38fSjmmv struct itimerval timer;
22328cce38fSjmmv timer.it_interval.tv_sec = 0;
22428cce38fSjmmv timer.it_interval.tv_usec = 0;
22528cce38fSjmmv timer.it_value.tv_sec = 0;
22628cce38fSjmmv timer.it_value.tv_usec = ms * 1000;
22728cce38fSjmmv ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0);
22828cce38fSjmmv }
22928cce38fSjmmv
230ac555471Sjmmv static void *
threadfunc(void * arg)231ac555471Sjmmv threadfunc(void *arg)
232ac555471Sjmmv {
2337baa2850Sjoerg int i, ret;
234ac555471Sjmmv
23528cce38fSjmmv printf("Entering loop\n");
2368a0380e3Sjmmv for (i = 0; i < 500; ) {
23728cce38fSjmmv if ((i & 1) != 0) {
2387baa2850Sjoerg do {
2397baa2850Sjoerg ret = sem_wait(&sem);
2407baa2850Sjoerg } while (ret == -1 && errno == EINTR);
2417baa2850Sjoerg ATF_REQUIRE(ret == 0);
24228cce38fSjmmv } else {
2437baa2850Sjoerg ret = sem_trywait(&sem);
24428cce38fSjmmv if (ret == -1) {
24528cce38fSjmmv ATF_REQUIRE(errno == EAGAIN);
246ac555471Sjmmv continue;
247ac555471Sjmmv }
24828cce38fSjmmv }
249ac555471Sjmmv printf("%s: %d\n", __func__, i);
2508a0380e3Sjmmv alarm_ms(5);
251ac555471Sjmmv i++;
252ac555471Sjmmv }
253ac555471Sjmmv
254ac555471Sjmmv return NULL;
255ac555471Sjmmv }
256ac555471Sjmmv
25728cce38fSjmmv static void
before_start_test(const bool use_pthread)25828cce38fSjmmv before_start_test(const bool use_pthread)
259ac555471Sjmmv {
260ac555471Sjmmv pthread_t t;
261ac555471Sjmmv
262ac555471Sjmmv SEM_REQUIRE(sem_init(&sem, 0, 0));
263ac555471Sjmmv ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler));
264ac555471Sjmmv
2658a0380e3Sjmmv alarm_ms(5);
26628cce38fSjmmv
26728cce38fSjmmv if (use_pthread) {
26828cce38fSjmmv PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL));
269ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(t, NULL));
27028cce38fSjmmv } else {
27128cce38fSjmmv threadfunc(NULL);
27228cce38fSjmmv }
27328cce38fSjmmv }
27428cce38fSjmmv
27528cce38fSjmmv ATF_TC(before_start_no_threads);
ATF_TC_HEAD(before_start_no_threads,tc)27628cce38fSjmmv ATF_TC_HEAD(before_start_no_threads, tc)
27728cce38fSjmmv {
27828cce38fSjmmv atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any "
27928cce38fSjmmv "thread running");
2808a0380e3Sjmmv atf_tc_set_md_var(tc, "timeout", "40");
28128cce38fSjmmv }
ATF_TC_BODY(before_start_no_threads,tc)28228cce38fSjmmv ATF_TC_BODY(before_start_no_threads, tc)
28328cce38fSjmmv {
28428cce38fSjmmv before_start_test(false);
28528cce38fSjmmv }
28628cce38fSjmmv
28728cce38fSjmmv ATF_TC(before_start_one_thread);
ATF_TC_HEAD(before_start_one_thread,tc)28828cce38fSjmmv ATF_TC_HEAD(before_start_one_thread, tc)
28928cce38fSjmmv {
29028cce38fSjmmv atf_tc_set_md_var(tc, "descr", "Checks using semaphores before "
29128cce38fSjmmv "starting one thread");
2928a0380e3Sjmmv atf_tc_set_md_var(tc, "timeout", "40");
29328cce38fSjmmv }
ATF_TC_BODY(before_start_one_thread,tc)29428cce38fSjmmv ATF_TC_BODY(before_start_one_thread, tc)
29528cce38fSjmmv {
29628cce38fSjmmv before_start_test(true);
297ac555471Sjmmv }
298ac555471Sjmmv
ATF_TP_ADD_TCS(tp)299ac555471Sjmmv ATF_TP_ADD_TCS(tp)
300ac555471Sjmmv {
301ac555471Sjmmv ATF_TP_ADD_TC(tp, named);
302ac555471Sjmmv ATF_TP_ADD_TC(tp, unnamed);
30328cce38fSjmmv ATF_TP_ADD_TC(tp, before_start_no_threads);
30428cce38fSjmmv ATF_TP_ADD_TC(tp, before_start_one_thread);
305ac555471Sjmmv
306ac555471Sjmmv return atf_no_error();
307ac555471Sjmmv }
308