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@us.ibm.com)
28  *      -written
29  *    11/09/2001 Manoj Iyer (manjo@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 
semup(int semid)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 
semdown(int semid)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 
delayloop()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 
mainloop(int semid)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 
main(int argc,char * argv[])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