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 44 static int shmid = -1; 45 static key_t shmkey; 46 static char *shm_buf; 47 48 static int semid = -1; 49 static key_t semkey; 50 static struct sembuf sop[2]; 51 52 static size_t pgsize; 53 static pid_t pid; 54 55 int 56 setup(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 96 void 97 cleanup(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 107 static void 108 Wait(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 118 static void 119 Sig(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 129 int 130 test(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