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 <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/ipc.h> 36 #include <sys/msg.h> 37 #include <sys/shm.h> 38 #include <sys/sem.h> 39 #include <signal.h> 40 #include <errno.h> 41 #include <err.h> 42 43 #include "stress.h" 44 45 int shmid = -1; 46 key_t shmkey; 47 char *shm_buf; 48 49 int semid = -1; 50 key_t semkey; 51 struct sembuf sop[2]; 52 53 size_t pgsize; 54 pid_t pid; 55 56 int 57 setup(int nb) 58 { 59 int seed; 60 61 pgsize = sysconf(_SC_PAGESIZE); 62 63 seed = getpid(); 64 // printf("seed(%d) = %d\n", getpid(), seed); 65 shmkey = ftok("/tmp", seed); 66 if ((shmid = shmget(shmkey, 10 * pgsize, IPC_CREAT | IPC_EXCL | 0640)) == -1) { 67 if (errno == ENOSPC) { 68 fprintf(stderr, "Max number of semaphores reached.\n"); 69 exit(1); 70 } 71 err(1, "shmget (%s:%d)", __FILE__, __LINE__); 72 } 73 74 shm_buf = 0; 75 if ((shm_buf = shmat(shmid, NULL, 0)) == (void *) -1) 76 err(1, "sender: shmat (%s:%d)", __FILE__, __LINE__); 77 78 // printf("seed(%d) = %d\n", getpid(), seed); 79 semkey = ftok("/var", seed); 80 if ((semid = semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0640)) == -1) { 81 if (errno == ENOSPC) { 82 fprintf(stderr, "Max number of semaphores reached.\n"); 83 exit(1); 84 } 85 err(1, "semget (%s:%d)", __FILE__, __LINE__); 86 } 87 /* Initialize the semaphore. */ 88 sop[0].sem_num = 0; 89 sop[0].sem_op = 0; /* This is the number of runs without queuing. */ 90 sop[0].sem_flg = 0; 91 sop[1].sem_num = 1; 92 sop[1].sem_op = 0; /* This is the number of runs without queuing. */ 93 sop[1].sem_flg = 0; 94 if (semop(semid, sop, 2) == -1) 95 err(1, "init: semop (%s:%d)", __FILE__, __LINE__); 96 return (0); 97 } 98 99 void 100 cleanup(void) 101 { 102 if (shmid != -1) 103 if (shmctl(shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) 104 warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); 105 if (semid != -1) 106 if (semctl(semid, 0, IPC_RMID, 0) == -1 && errno != EINVAL) 107 warn("shmctl IPC_RMID (%s:%d)", __FILE__, __LINE__); 108 } 109 110 static void 111 Wait(int i) { 112 sop[0].sem_num = i; 113 sop[0].sem_op = -1; 114 if (semop(semid, sop, 1) == -1) { 115 if (errno != EINTR && errno != EIDRM && errno != EINVAL) 116 warn("Wait: semop (%s:%d)", __FILE__, __LINE__); 117 done_testing = 1; 118 } 119 } 120 121 static void 122 Sig(int i) { 123 sop[0].sem_num = i; 124 sop[0].sem_op = 1; 125 if (semop(semid, sop, 1) == -1) { 126 if (errno != EINTR && errno != EIDRM && errno != EINVAL) 127 warn("Sig: semop (%s:%d)", __FILE__, __LINE__); 128 done_testing = 1; 129 } 130 } 131 132 int 133 test(void) 134 { 135 int i = 0; 136 137 pid = fork(); 138 if (pid == -1) { 139 perror("fork"); 140 exit(2); 141 } 142 143 if (pid == 0) { /* child */ 144 i = 0; 145 for (;;) { 146 Wait(1); 147 if (done_testing == 1) 148 break; 149 if (shm_buf[i] != (i % 128)) { 150 fprintf(stderr, 151 "child %d: expected %d, got %d\n", 152 getpid(), i % 128, shm_buf[i]); 153 break; 154 } 155 shm_buf[i] = 0; 156 i = (i + 1) % (10 * pgsize); 157 shm_buf[i] = (i % 128); 158 i = (i + 1) % (10 * pgsize); 159 Sig(0); 160 } 161 exit(0); 162 163 } else { /* parent */ 164 i = 0; 165 for (;;) { 166 shm_buf[i] = (i % 128); 167 Sig(1); 168 i = (i + 1) % (10 * pgsize); 169 Wait(0); 170 if (done_testing == 1) 171 break; 172 if (shm_buf[i] != (i % 128)) { 173 fprintf(stderr, 174 "parent(%d): expected %d, got %d\n", 175 getpid(), i % 128, shm_buf[i]); 176 break; 177 } 178 shm_buf[i] = 0; 179 i = (i + 1) % (10 * pgsize); 180 } 181 kill(pid, SIGHUP); 182 kill(pid, SIGKILL); 183 } 184 return (0); 185 } 186