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