1276478Sngie/* $NetBSD: t_sem.c,v 1.8 2014/11/04 00:20:19 justin Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie/*- 30272343Sngie * Copyright (c)2004 YAMAMOTO Takashi, 31272343Sngie * All rights reserved. 32272343Sngie * 33272343Sngie * Redistribution and use in source and binary forms, with or without 34272343Sngie * modification, are permitted provided that the following conditions 35272343Sngie * are met: 36272343Sngie * 1. Redistributions of source code must retain the above copyright 37272343Sngie * notice, this list of conditions and the following disclaimer. 38272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 39272343Sngie * notice, this list of conditions and the following disclaimer in the 40272343Sngie * documentation and/or other materials provided with the distribution. 41272343Sngie * 42272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52272343Sngie * SUCH DAMAGE. 53272343Sngie */ 54272343Sngie 55272343Sngie/**************************************************************************** 56272343Sngie * 57272343Sngie * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>. 58272343Sngie * All rights reserved. 59272343Sngie * 60272343Sngie * Redistribution and use in source and binary forms, with or without 61272343Sngie * modification, are permitted provided that the following conditions 62272343Sngie * are met: 63272343Sngie * 1. Redistributions of source code must retain the above copyright 64272343Sngie * notice(s), this list of conditions and the following disclaimer as 65272343Sngie * the first lines of this file unmodified other than the possible 66272343Sngie * addition of one or more copyright notices. 67272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 68272343Sngie * notice(s), this list of conditions and the following disclaimer in 69272343Sngie * the documentation and/or other materials provided with the 70272343Sngie * distribution. 71272343Sngie * 72272343Sngie * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 73272343Sngie * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 74272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 75272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 76272343Sngie * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 77272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 78272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 79272343Sngie * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 80272343Sngie * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 81272343Sngie * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 82272343Sngie * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83272343Sngie * 84272343Sngie ****************************************************************************/ 85272343Sngie 86272343Sngie#include <sys/cdefs.h> 87272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008, 2010\ 88272343Sngie The NetBSD Foundation, inc. All rights reserved."); 89276478Sngie__RCSID("$NetBSD: t_sem.c,v 1.8 2014/11/04 00:20:19 justin Exp $"); 90272343Sngie 91272343Sngie#include <errno.h> 92272343Sngie#include <fcntl.h> 93272343Sngie#include <pthread.h> 94272343Sngie#include <semaphore.h> 95272343Sngie#include <signal.h> 96272343Sngie#include <stdio.h> 97272343Sngie#include <stdlib.h> 98272343Sngie#include <string.h> 99272343Sngie#include <unistd.h> 100272343Sngie 101272343Sngie#include <atf-c.h> 102272343Sngie 103272343Sngie#include "h_common.h" 104272343Sngie 105272343Sngie#define NTHREADS 10 106272343Sngie 107272343Sngie#define _LIBC_R_ 108272343Sngie 109272343Sngie#define SEM_REQUIRE(x) \ 110272343Sngie ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno)) 111272343Sngie 112272343Sngiestatic sem_t sem; 113272343Sngie 114276478Sngie#ifdef __FreeBSD__ 115276478Sngie#include <sys/time.h> 116276478Sngie#endif 117276478Sngie 118272343SngieATF_TC(named); 119272343SngieATF_TC_HEAD(named, tc) 120272343Sngie{ 121272343Sngie atf_tc_set_md_var(tc, "descr", "Checks named semaphores"); 122272343Sngie} 123272343SngieATF_TC_BODY(named, tc) 124272343Sngie{ 125272343Sngie sem_t *semp; 126272343Sngie 127272343Sngie ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno)); 128272343Sngie 129272343Sngie printf("Test begin\n"); 130272343Sngie 131272343Sngie (void) sem_unlink("/foo"); 132272343Sngie semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0); 133272343Sngie ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno)); 134272343Sngie SEM_REQUIRE(sem_close(semp)); 135272343Sngie SEM_REQUIRE(sem_unlink("/foo")); 136272343Sngie 137272343Sngie printf("Test end\n"); 138272343Sngie} 139272343Sngie 140272343SngieATF_TC(unnamed); 141272343SngieATF_TC_HEAD(unnamed, tc) 142272343Sngie{ 143272343Sngie atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores"); 144272343Sngie} 145272343Sngie 146272343Sngiestatic void * 147272343Sngieentry(void * a_arg) 148272343Sngie{ 149272343Sngie pthread_t self = pthread_self(); 150272343Sngie sem_t *semp = (sem_t *) a_arg; 151272343Sngie 152272343Sngie printf("Thread %p waiting for semaphore...\n", self); 153272343Sngie sem_wait(semp); 154272343Sngie printf("Thread %p got semaphore\n", self); 155272343Sngie 156272343Sngie return NULL; 157272343Sngie} 158272343Sngie 159272343SngieATF_TC_BODY(unnamed, tc) 160272343Sngie{ 161272343Sngie sem_t sem_a, sem_b; 162272343Sngie pthread_t threads[NTHREADS]; 163272343Sngie unsigned i, j; 164272343Sngie int val; 165272343Sngie 166272343Sngie ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno)); 167272343Sngie 168272343Sngie printf("Test begin\n"); 169272343Sngie 170272343Sngie SEM_REQUIRE(sem_init(&sem_b, 0, 0)); 171272343Sngie SEM_REQUIRE(sem_getvalue(&sem_b, &val)); 172272343Sngie ATF_REQUIRE_EQ(0, val); 173272343Sngie 174272343Sngie SEM_REQUIRE(sem_post(&sem_b)); 175272343Sngie SEM_REQUIRE(sem_getvalue(&sem_b, &val)); 176272343Sngie ATF_REQUIRE_EQ(1, val); 177272343Sngie 178272343Sngie SEM_REQUIRE(sem_wait(&sem_b)); 179272343Sngie ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1); 180272343Sngie ATF_REQUIRE_EQ(errno, EAGAIN); 181272343Sngie SEM_REQUIRE(sem_post(&sem_b)); 182272343Sngie SEM_REQUIRE(sem_trywait(&sem_b)); 183272343Sngie SEM_REQUIRE(sem_post(&sem_b)); 184272343Sngie SEM_REQUIRE(sem_wait(&sem_b)); 185272343Sngie SEM_REQUIRE(sem_post(&sem_b)); 186272343Sngie 187272343Sngie SEM_REQUIRE(sem_destroy(&sem_b)); 188272343Sngie 189272343Sngie SEM_REQUIRE(sem_init(&sem_a, 0, 0)); 190272343Sngie 191272343Sngie for (j = 0; j < 2; j++) { 192272343Sngie for (i = 0; i < NTHREADS; i++) { 193272343Sngie PTHREAD_REQUIRE(pthread_create(&threads[i], NULL, 194272343Sngie entry, (void *) &sem_a)); 195272343Sngie } 196272343Sngie 197272343Sngie for (i = 0; i < NTHREADS; i++) { 198272343Sngie usleep(10000); 199272343Sngie printf("main loop %u: posting...\n", j+1); 200272343Sngie SEM_REQUIRE(sem_post(&sem_a)); 201272343Sngie } 202272343Sngie 203272343Sngie for (i = 0; i < NTHREADS; i++) { 204272343Sngie PTHREAD_REQUIRE(pthread_join(threads[i], NULL)); 205272343Sngie } 206272343Sngie } 207272343Sngie 208272343Sngie SEM_REQUIRE(sem_destroy(&sem_a)); 209272343Sngie 210272343Sngie printf("Test end\n"); 211272343Sngie} 212272343Sngie 213272343Sngiestatic void 214272343Sngiesighandler(int signo) 215272343Sngie{ 216272343Sngie /* printf("signal %d\n", signo); */ 217272343Sngie 218272343Sngie ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal"); 219272343Sngie SEM_REQUIRE(sem_post(&sem)); 220272343Sngie} 221272343Sngie 222272343Sngiestatic void 223272343Sngiealarm_ms(const int ms) 224272343Sngie{ 225272343Sngie struct itimerval timer; 226272343Sngie timer.it_interval.tv_sec = 0; 227272343Sngie timer.it_interval.tv_usec = 0; 228272343Sngie timer.it_value.tv_sec = 0; 229272343Sngie timer.it_value.tv_usec = ms * 1000; 230272343Sngie ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0); 231272343Sngie} 232272343Sngie 233272343Sngiestatic void * 234272343Sngiethreadfunc(void *arg) 235272343Sngie{ 236272343Sngie int i, ret; 237272343Sngie 238272343Sngie printf("Entering loop\n"); 239272343Sngie for (i = 0; i < 500; ) { 240272343Sngie if ((i & 1) != 0) { 241272343Sngie do { 242272343Sngie ret = sem_wait(&sem); 243272343Sngie } while (ret == -1 && errno == EINTR); 244272343Sngie ATF_REQUIRE(ret == 0); 245272343Sngie } else { 246272343Sngie ret = sem_trywait(&sem); 247272343Sngie if (ret == -1) { 248272343Sngie ATF_REQUIRE(errno == EAGAIN); 249272343Sngie continue; 250272343Sngie } 251272343Sngie } 252272343Sngie printf("%s: %d\n", __func__, i); 253272343Sngie alarm_ms(5); 254272343Sngie i++; 255272343Sngie } 256272343Sngie 257272343Sngie return NULL; 258272343Sngie} 259272343Sngie 260272343Sngiestatic void 261272343Sngiebefore_start_test(const bool use_pthread) 262272343Sngie{ 263272343Sngie pthread_t t; 264272343Sngie 265272343Sngie SEM_REQUIRE(sem_init(&sem, 0, 0)); 266272343Sngie ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler)); 267272343Sngie 268272343Sngie alarm_ms(5); 269272343Sngie 270272343Sngie if (use_pthread) { 271272343Sngie PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL)); 272272343Sngie PTHREAD_REQUIRE(pthread_join(t, NULL)); 273272343Sngie } else { 274272343Sngie threadfunc(NULL); 275272343Sngie } 276272343Sngie} 277272343Sngie 278272343SngieATF_TC(before_start_no_threads); 279272343SngieATF_TC_HEAD(before_start_no_threads, tc) 280272343Sngie{ 281272343Sngie atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any " 282272343Sngie "thread running"); 283272343Sngie atf_tc_set_md_var(tc, "timeout", "40"); 284272343Sngie} 285272343SngieATF_TC_BODY(before_start_no_threads, tc) 286272343Sngie{ 287272343Sngie before_start_test(false); 288272343Sngie} 289272343Sngie 290272343SngieATF_TC(before_start_one_thread); 291272343SngieATF_TC_HEAD(before_start_one_thread, tc) 292272343Sngie{ 293272343Sngie atf_tc_set_md_var(tc, "descr", "Checks using semaphores before " 294272343Sngie "starting one thread"); 295272343Sngie atf_tc_set_md_var(tc, "timeout", "40"); 296272343Sngie} 297272343SngieATF_TC_BODY(before_start_one_thread, tc) 298272343Sngie{ 299272343Sngie before_start_test(true); 300272343Sngie} 301272343Sngie 302272343SngieATF_TP_ADD_TCS(tp) 303272343Sngie{ 304272343Sngie ATF_TP_ADD_TC(tp, named); 305272343Sngie ATF_TP_ADD_TC(tp, unnamed); 306272343Sngie ATF_TP_ADD_TC(tp, before_start_no_threads); 307272343Sngie ATF_TP_ADD_TC(tp, before_start_one_thread); 308272343Sngie 309272343Sngie return atf_no_error(); 310272343Sngie} 311