• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "lapi/sem.h"
44 
45 int verbose = 0;
46 int loops = 100;
47 int errors = 0;
48 
semup(int semid)49 int semup(int semid)
50 {
51 	struct sembuf semops;
52 	semops.sem_num = 0;
53 	semops.sem_op = 1;
54 	semops.sem_flg = SEM_UNDO;
55 	if (semop(semid, &semops, 1) == -1) {
56 		perror("semup");
57 		errors++;
58 		return 1;
59 	}
60 	return 0;
61 }
62 
semdown(int semid)63 int semdown(int semid)
64 {
65 	struct sembuf semops;
66 	semops.sem_num = 0;
67 	semops.sem_op = -1;
68 	semops.sem_flg = SEM_UNDO;
69 	if (semop(semid, &semops, 1) == -1) {
70 		perror("semdown");
71 		errors++;
72 		return 1;
73 	}
74 	return 0;
75 }
76 
delayloop()77 void delayloop()
78 {
79 	int delay;
80 	delay = 1 + ((100.0 * rand()) / RAND_MAX);
81 	if (verbose)
82 		printf("in delay function for %d microseconds\n", delay);
83 	usleep(delay);
84 }
85 
mainloop(int semid)86 void mainloop(int semid)
87 {
88 	int i;
89 	for (i = 0; i < loops; i++) {
90 		if (semdown(semid)) {
91 			printf("semdown failed\n");
92 		}
93 		if (verbose)
94 			printf("sem is down\n");
95 		delayloop();
96 		if (semup(semid)) {
97 			printf("semup failed\n");
98 		}
99 		if (verbose)
100 			printf("sem is up\n");
101 	}
102 }
103 
main(int argc,char * argv[])104 int main(int argc, char *argv[])
105 {
106 	int semid, opt;
107 	union semun semunion;
108 	extern char *optarg;
109 	pid_t pid;
110 	int chstat;
111 
112 	while ((opt = getopt(argc, argv, "l:vh")) != EOF) {
113 		switch ((char)opt) {
114 		case 'l':
115 			loops = atoi(optarg);
116 			break;
117 		case 'v':
118 			verbose = 1;
119 			break;
120 		case 'h':
121 		default:
122 			printf("Usage: -l loops [-v]\n");
123 			exit(1);
124 		}
125 	}
126 
127 	/* set up the semaphore */
128 	if ((semid = semget((key_t) 9142, 1, 0666 | IPC_CREAT)) < 0) {
129 		printf("error in semget()\n");
130 		exit(-1);
131 	}
132 	semunion.val = 1;
133 	if (semctl(semid, 0, SETVAL, semunion) == -1) {
134 		printf("error in semctl\n");
135 	}
136 
137 	if ((pid = fork()) < 0) {
138 		printf("fork error\n");
139 		exit(-1);
140 	}
141 	if (pid) {
142 		/* parent */
143 		srand(pid);
144 		mainloop(semid);
145 		waitpid(pid, &chstat, 0);
146 		if (!WIFEXITED(chstat)) {
147 			printf("child exited with status\n");
148 			exit(-1);
149 		}
150 		if (semctl(semid, 0, IPC_RMID, semunion) == -1) {
151 			printf("error in semctl\n");
152 		}
153 		if (errors) {
154 			printf("FAIL: there were %d errors\n", errors);
155 		} else {
156 			printf("PASS: error count is 0\n");
157 		}
158 		exit(errors);
159 	} else {
160 		/* child */
161 		mainloop(semid);
162 	}
163 	exit(0);
164 }
165