1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * FILE : sem01.c 22 * DESCRIPTION : Creates a semaphore and two processes. The processes 23 * each go through a loop where they semdown, delay for a 24 * random amount of time, and semup, so they will almost 25 * always be fighting for control of the semaphore. 26 * HISTORY: 27 * 01/15/2001 Paul Larson (plars (at) us.ibm.com) 28 * -written 29 * 11/09/2001 Manoj Iyer (manjo (at) ausin.ibm.com) 30 * Modified. 31 * - Removed compiler warnings. 32 * added exit to the end of function main() 33 * 34 */ 35 36 #include <unistd.h> 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include <errno.h> 40 #include <sys/types.h> 41 #include <sys/wait.h> 42 #include <sys/ipc.h> 43 #include <sys/sem.h> 44 #include "lapi/semun.h" 45 46 int verbose = 0; 47 int loops = 100; 48 int errors = 0; 49 50 int semup(int semid) 51 { 52 struct sembuf semops; 53 semops.sem_num = 0; 54 semops.sem_op = 1; 55 semops.sem_flg = SEM_UNDO; 56 if (semop(semid, &semops, 1) == -1) { 57 perror("semup"); 58 errors++; 59 return 1; 60 } 61 return 0; 62 } 63 64 int semdown(int semid) 65 { 66 struct sembuf semops; 67 semops.sem_num = 0; 68 semops.sem_op = -1; 69 semops.sem_flg = SEM_UNDO; 70 if (semop(semid, &semops, 1) == -1) { 71 perror("semdown"); 72 errors++; 73 return 1; 74 } 75 return 0; 76 } 77 78 void delayloop() 79 { 80 int delay; 81 delay = 1 + ((100.0 * rand()) / RAND_MAX); 82 if (verbose) 83 printf("in delay function for %d microseconds\n", delay); 84 usleep(delay); 85 } 86 87 void mainloop(int semid) 88 { 89 int i; 90 for (i = 0; i < loops; i++) { 91 if (semdown(semid)) { 92 printf("semdown failed\n"); 93 } 94 if (verbose) 95 printf("sem is down\n"); 96 delayloop(); 97 if (semup(semid)) { 98 printf("semup failed\n"); 99 } 100 if (verbose) 101 printf("sem is up\n"); 102 } 103 } 104 105 int main(int argc, char *argv[]) 106 { 107 int semid, opt; 108 union semun semunion; 109 extern char *optarg; 110 pid_t pid; 111 int chstat; 112 113 while ((opt = getopt(argc, argv, "l:vh")) != EOF) { 114 switch ((char)opt) { 115 case 'l': 116 loops = atoi(optarg); 117 break; 118 case 'v': 119 verbose = 1; 120 break; 121 case 'h': 122 default: 123 printf("Usage: -l loops [-v]\n"); 124 exit(1); 125 } 126 } 127 128 /* set up the semaphore */ 129 if ((semid = semget((key_t) 9142, 1, 0666 | IPC_CREAT)) < 0) { 130 printf("error in semget()\n"); 131 exit(-1); 132 } 133 semunion.val = 1; 134 if (semctl(semid, 0, SETVAL, semunion) == -1) { 135 printf("error in semctl\n"); 136 } 137 138 if ((pid = fork()) < 0) { 139 printf("fork error\n"); 140 exit(-1); 141 } 142 if (pid) { 143 /* parent */ 144 srand(pid); 145 mainloop(semid); 146 waitpid(pid, &chstat, 0); 147 if (!WIFEXITED(chstat)) { 148 printf("child exited with status\n"); 149 exit(-1); 150 } 151 if (semctl(semid, 0, IPC_RMID, semunion) == -1) { 152 printf("error in semctl\n"); 153 } 154 if (errors) { 155 printf("FAIL: there were %d errors\n", errors); 156 } else { 157 printf("PASS: error count is 0\n"); 158 } 159 exit(errors); 160 } else { 161 /* child */ 162 mainloop(semid); 163 } 164 exit(0); 165 } 166