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