1/*- 2 * Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28/* Test shared memory */ 29 30#include <sys/param.h> 31#include <sys/ipc.h> 32#include <sys/msg.h> 33#include <sys/sem.h> 34#include <sys/shm.h> 35#include <err.h> 36#include <errno.h> 37#include <signal.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <unistd.h> 41 42#include "stress.h" 43 44static int shmid = -1; 45static key_t shmkey; 46static char *shm_buf; 47 48static int semid = -1; 49static key_t semkey; 50static struct sembuf sop[2]; 51 52static size_t pgsize; 53static pid_t pid; 54 55int 56setup(int nb __unused) 57{ 58 int seed; 59 60 pgsize = sysconf(_SC_PAGESIZE); 61 62 seed = getpid(); 63 shmkey = ftok("/tmp", seed); 64 if ((shmid = shmget(shmkey, 10 * pgsize, IPC_CREAT | IPC_EXCL | 0640)) == -1) { 65 if (errno == ENOSPC) { 66 fprintf(stderr, "Max number of semaphores reached.\n"); 67 exit(1); 68 } 69 err(1, "shmget (%s:%d)", __FILE__, __LINE__); 70 } 71 72 shm_buf = 0; 73 if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1) 74 err(1, "sender: shmat (%s:%d)", __FILE__, __LINE__); 75 76 semkey = ftok("/var", seed); 77 if ((semid = semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0640)) == -1) { 78 if (errno == ENOSPC) { 79 fprintf(stderr, "Max number of semaphores reached.\n"); 80 exit(1); 81 } 82 err(1, "semget (%s:%d)", __FILE__, __LINE__); 83 } 84 /* Initialize the semaphore. */ 85 sop[0].sem_num = 0; 86 sop[0].sem_op = 0; /* This is the number of runs without queuing. */ 87 sop[0].sem_flg = 0; 88 sop[1].sem_num = 1; 89 sop[1].sem_op = 0; /* This is the number of runs without queuing. */ 90 sop[1].sem_flg = 0; 91 if (semop(semid, sop, 2) == -1) 92 err(1, "init: semop (%s:%d)", __FILE__, __LINE__); 93 return (0); 94} 95 96void 97cleanup(void) 98{ 99 if (shmid != -1) 100 if (shmctl(shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) 101 warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); 102 if (semid != -1) 103 if (semctl(semid, 0, IPC_RMID, 0) == -1 && errno != EINVAL) 104 warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); 105} 106 107static void 108Wait(int i) { 109 sop[0].sem_num = i; 110 sop[0].sem_op = -1; 111 if (semop(semid, sop, 1) == -1) { 112 if (errno != EINTR && errno != EIDRM && errno != EINVAL) 113 warn("Wait: semop (%s:%d)", __FILE__, __LINE__); 114 done_testing = 1; 115 } 116} 117 118static void 119Sig(int i) { 120 sop[0].sem_num = i; 121 sop[0].sem_op = 1; 122 if (semop(semid, sop, 1) == -1) { 123 if (errno != EINTR && errno != EIDRM && errno != EINVAL) 124 warn("Sig: semop (%s:%d)", __FILE__, __LINE__); 125 done_testing = 1; 126 } 127} 128 129int 130test(void) 131{ 132 int i = 0; 133 134 pid = fork(); 135 if (pid == -1) { 136 perror("fork"); 137 exit(2); 138 } 139 140 if (pid == 0) { /* child */ 141 i = 0; 142 for (;;) { 143 Wait(1); 144 if (done_testing == 1) 145 break; 146 if (shm_buf[i] != (i % 128)) { 147 fprintf(stderr, 148 "child %d: expected %d, got %d\n", 149 getpid(), i % 128, shm_buf[i]); 150 break; 151 } 152 shm_buf[i] = 0; 153 i = (i + 1) % (10 * pgsize); 154 shm_buf[i] = (i % 128); 155 i = (i + 1) % (10 * pgsize); 156 Sig(0); 157 } 158 _exit(0); 159 160 } else { /* parent */ 161 i = 0; 162 for (;;) { 163 shm_buf[i] = (i % 128); 164 Sig(1); 165 i = (i + 1) % (10 * pgsize); 166 Wait(0); 167 if (done_testing == 1) 168 break; 169 if (shm_buf[i] != (i % 128)) { 170 fprintf(stderr, 171 "parent(%d): expected %d, got %d\n", 172 getpid(), i % 128, shm_buf[i]); 173 break; 174 } 175 shm_buf[i] = 0; 176 i = (i + 1) % (10 * pgsize); 177 } 178 kill(pid, SIGHUP); 179 kill(pid, SIGKILL); 180 } 181 return (0); 182} 183