How does the behavior of 3000pc change if you delete lines 149 and 152 (the if s
ID: 3599384 • Letter: H
Question
How does the behavior of 3000pc change if you delete lines 149 and 152 (the if statement in wakeup_consumer())? Why? (Explain what the program does after this change and why it may be problematic.)
/* 3000pc.c */
2
3
4
5
6
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <semaphore.h>
17 #include <string.h>
18 #include <time.h>
19
20 #define QUEUESIZE 32
21 #define WORDSIZE 16
22
23 const int wordlist_size = 27;
24 const char *wordlist[] = {
25 "Alpha",
26 "Bravo",
27 "Charlie",
28 "Delta",
29 "Echo",
30 "Foxtrot",
31 "Golf",
32 "Hotel",
33 "India",
34 "Juliet",
35 "Kilo",
36 "Lima",
37 "Mike",
38 "November",
39 "Oscar",
40 "Papa",
41 "Quebec",
42 "Romeo",
43 "Sierra",
44 "Tango",
45 "Uniform",
46 "Victor",
47 "Whiskey",
48 "X-ray",
49 "Yankee",
50 "Zulu",
51 "Dash"
52 };
53
54 typedef struct entry {
55 char word[WORDSIZE];
56 sem_t lock;
57 } entry;
58
59 typedef struct shared {
60 int prod_waiting;
61 int con_waiting;
62 entry queue[QUEUESIZE];
63 int last_produced;
64 int last_consumed;
65 pid_t prod_pid;
66 pid_t con_pid;
67 int prod_count;
68 int con_count;
69 } shared;
70
71
72 void report_error(char *error)
73 {
74 fprintf(stderr, "Error: %s ", error);
75 }
76
77 void usage_exit(char *progname)
78 {
79 fprintf(stderr,
80 "Usage: %s <event count> <prod delay int> <con delay int> ",
81 progname);
82 exit(-1);
83 }
84
85 void producer_handler(int the_signal)
86 {
87 if (the_signal == SIGUSR1) {
88 fprintf(stderr, "Producer received SIGUSR1. ");
89 return;
90
91 } else {
92 fprintf(stderr, "Producer: No handler for for signal %d?! ",
93 the_signal);
94 return;
95 }
96 }
97
98 void consumer_handler(int the_signal)
99 {
100 if (the_signal == SIGUSR1) {
101 fprintf(stderr, "Consumer received SIGUSR1. ");
102 return;
103 } else {
104 fprintf(stderr, "Consumer: No handler for for signal %d?! ",
105 the_signal);
106 return;
107 }
108 }
109
110 void pick_word(char *word)
111 {
112 int pick;
113
114 pick = random() % wordlist_size;
115
116 strcpy(word, wordlist[pick]);
117 }
118
119 void wait_for_producer(shared *s)
120 {
121 struct timespec delay;
122
123 delay.tv_sec = 100;
124 delay.tv_nsec = 0;
125
126 s->con_waiting = 1;
127
128 while (s->con_waiting) {
129 nanosleep(&delay, NULL);
130 }
131 }
132
133 void wait_for_consumer(shared *s)
134 {
135 struct timespec delay;
136
137 delay.tv_sec = 100;
138 delay.tv_nsec = 0;
139
140 s->prod_waiting = 1;
141
142 while (s->prod_waiting) {
143 nanosleep(&delay, NULL);
144 }
145 }
146
147 void wakeup_consumer(shared *s)
148 {
149 if (s->con_waiting) {
150 s->con_waiting = 0;
151 kill(s->con_pid, SIGUSR1);
152 }
153 }
154
155 void wakeup_producer(shared *s)
156 {
157 if (s->prod_waiting) {
158 s->prod_waiting = 0;
159 kill(s->prod_pid, SIGUSR1);
160 }
161 }
162
163 void output_word(int c, char *w)
164 {
165 printf("Word %d: %s ", c, w);
166 }
167
168 int queue_word(char *word, shared *s)
169 {
170 entry *e;
171 int current, retval;
172
173 current = (s->last_produced + 1) % QUEUESIZE;
174
175 e = &s->queue[current];
176
177 sem_wait(&e->lock);
178
179 if (e->word[0] != '') {
180 /* consumer hasn't consumed this entry yet */
181 sem_post(&e->lock);
182 wait_for_consumer(s);
183 sem_wait(&e->lock);
184 }
185
186 if (e->word[0] != '') {
187 fprintf(stderr, "ERROR: No room for producer after waiting! ");
188 retval = -1;
189 goto done;
190 } else {
191 strncpy(e->word, word, WORDSIZE);
192 s->last_produced = current;
193 s->prod_count++;
194 wakeup_consumer(s);
195 retval = 0;
196 goto done;
197 }
198
199 done:
200 sem_post(&e->lock);
201 return retval;
202 }
203
204 int get_next_word(char *word, shared *s)
205 {
206 entry *e;
207 int current, retval;
208
209 current = (s->last_consumed + 1) % QUEUESIZE;
210
211 e = &s->queue[current];
212
213 sem_wait(&e->lock);
214
215 if (e->word[0] == '') {
216 /* producer hasn't filled in this entry yet */
217 sem_post(&e->lock);
218 wait_for_producer(s);
219 sem_wait(&e->lock);
220 }
221
222 if (e->word[0] == '') {
223 fprintf(stderr, "ERROR: Nothing for consumer after waiting! ");
224 retval = -1;
225 goto done;
226 } else {
227 strncpy(word, e->word, WORDSIZE);
228 e->word[0] = '';
229 s->last_consumed = current;
230 s->con_count++;
231 wakeup_producer(s);
232 retval = 0;
233 goto done;
234 }
235
236 done:
237 sem_post(&e->lock);
238 return retval;
239 }
240
241 void producer(shared *s, int event_count, int producer_delay_interval)
242 {
243 char word[WORDSIZE];
244 int i;
245 struct sigaction signal_handler_struct;
246
247 memset (&signal_handler_struct, 0, sizeof(signal_handler_struct));
248 signal_handler_struct.sa_handler = producer_handler;
249
250 if (sigaction(SIGUSR1, &signal_handler_struct, NULL)) {
251 fprintf(stderr, "Producer couldn't register SIGUSR1 handler. ");
252 }
253
254 for (i=0; i < event_count; i++) {
255 pick_word(word);
256 queue_word(word, s);
257 if (producer_delay_interval > 0) {
258 if (i % producer_delay_interval == 0) {
259 sleep(1);
260 }
261 }
262 }
263
264 printf("Producer finished. ");
265 exit(0);
266 }
267
268 void consumer(shared *s, int event_count, int consumer_delay_interval)
269 {
270 char word[WORDSIZE];
271 int i;
272 struct sigaction signal_handler_struct;
273
274 memset (&signal_handler_struct, 0, sizeof(signal_handler_struct));
275 signal_handler_struct.sa_handler = consumer_handler;
276
277 if (sigaction(SIGUSR1, &signal_handler_struct, NULL)) {
278 fprintf(stderr, "Consumer couldn't register SIGUSR1 handler. ");
279 }
280
281 for (i=0; i < event_count; i++) {
282 get_next_word(word, s);
283 output_word(s->con_count, word);
284 if (consumer_delay_interval > 0) {
285 if (i % consumer_delay_interval == 0) {
286 sleep(1);
287 }
288 }
289 }
290
291 printf("Consumer finished. ");
292 exit(0);
293 }
294
295 void init_shared(shared *s)
296 {
297 int i;
298
299 s->con_waiting = 0;
300 s->last_consumed = -1;
301
302 s->prod_waiting = 0;
303 s->last_produced = -1;
304
305 s->prod_pid = -1;
306 s->con_pid = -1;
307
308 s->prod_count = 0;
309 s->con_count = 0;
310
311 for (i=0; i<QUEUESIZE; i++) {
312 s->queue[i].word[0] = '';
313 /* semaphore is shared between processes,
314 and initial value is 1 (unlocked) */
315 sem_init(&s->queue[i].lock, 1, 1);
316 }
317 }
318
319 int main(int argc, char *argv[])
320 {
321 int pid, count, prod_interval, con_interval;
322
323 shared *s;
324
325 srandom(42);
326
327 if (argc < 4) {
328 if (argc < 1) {
329 report_error("no command line");
330 usage_exit(argv[0]);
331 } else {
332 report_error("Not enough arguments");
333 usage_exit(argv[0]);
334 }
335 }
336
337 count = atoi(argv[1]);
338 prod_interval = atoi(argv[2]);
339 con_interval = atoi(argv[3]);
340
341 s = (shared *) mmap(NULL, sizeof(shared),
342 PROT_READ|PROT_WRITE,
343 MAP_SHARED|MAP_ANONYMOUS, -1, 0);
344
345 if (s == MAP_FAILED) {
346 report_error(strerror(errno));
347 }
348
349 init_shared(s);
350
351 pid = fork();
352
353 if (pid) {
354 /* producer */
355 s->prod_pid = getpid();
356 producer(s, count, prod_interval);
357 } else {
358 /* consumer */
359 s->con_pid = getpid();
360 consumer(s, count, con_interval);
361 }
362
363 /* This line should never be reached */
364 return -1;
365 }
Explanation / Answer
#include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <semaphore.h>
17 #include <string.h>
18 #include <time.h>
19
20 #define QUEUESIZE 32
21 #define WORDSIZE 16
22
23 const int wordlist_size = 27;
24 const char *wordlist[] = {
25 "Alpha",
26 "Bravo",
27 "Charlie",
28 "Delta",
29 "Echo",
30 "Foxtrot",
31 "Golf",
32 "Hotel",
33 "India",
34 "Juliet",
35 "Kilo",
36 "Lima",
37 "Mike",
38 "November",
39 "Oscar",
40 "Papa",
41 "Quebec",
42 "Romeo",
43 "Sierra",
44 "Tango",
45 "Uniform",
46 "Victor",
47 "Whiskey",
48 "X-ray",
49 "Yankee",
50 "Zulu",
51 "Dash"
52 };
53
54 typedef struct entry {
55 char word[WORDSIZE];
56 sem_t lock;
57 } entry;
58
59 typedef struct shared {
60 int prod_waiting;
61 int con_waiting;
62 entry queue[QUEUESIZE];
63 int last_produced;
64 int last_consumed;
65 pid_t prod_pid;
66 pid_t con_pid;
67 int prod_count;
68 int con_count;
69 } shared;
70
71
72 void report_error(char *error)
73 {
74 fprintf(stderr, "Error: %s ", error);
75 }
76
77 void usage_exit(char *progname)
78 {
79 fprintf(stderr,
80 "Usage: %s <event count> <prod delay int> <con delay int> ",
81 progname);
82 exit(-1);
83 }
84
85 void producer_handler(int the_signal)
86 {
87 if (the_signal == SIGUSR1) {
88 fprintf(stderr, "Producer received SIGUSR1. ");
89 return;
90
91 } else {
92 fprintf(stderr, "Producer: No handler for for signal %d?! ",
93 the_signal);
94 return;
95 }
96 }
97
98 void consumer_handler(int the_signal)
99 {
100 if (the_signal == SIGUSR1) {
101 fprintf(stderr, "Consumer received SIGUSR1. ");
102 return;
103 } else {
104 fprintf(stderr, "Consumer: No handler for for signal %d?! ",
105 the_signal);
106 return;
107 }
108 }
109
110 void pick_word(char *word)
111 {
112 int pick;
113
114 pick = random() % wordlist_size;
115
116 strcpy(word, wordlist[pick]);
117 }
118
119 void wait_for_producer(shared *s)
120 {
121 struct timespec delay;
122
123 delay.tv_sec = 100;
124 delay.tv_nsec = 0;
125
126 s->con_waiting = 1;
127
128 while (s->con_waiting) {
129 nanosleep(&delay, NULL);
130 }
131 }
132
133 void wait_for_consumer(shared *s)
134 {
135 struct timespec delay;
136
137 delay.tv_sec = 100;
138 delay.tv_nsec = 0;
139
140 s->prod_waiting = 1;
141
142 while (s->prod_waiting) {
143 nanosleep(&delay, NULL);
144 }
145 }
146
147 void wakeup_consumer(shared *s)
148 {
149 if (s->con_waiting) {
150 s->con_waiting = 0;
151 kill(s->con_pid, SIGUSR1);
152 }
153 }
154
155 void wakeup_producer(shared *s)
156 {
157 if (s->prod_waiting) {
158 s->prod_waiting = 0;
159 kill(s->prod_pid, SIGUSR1);
160 }
161 }
162
163 void output_word(int c, char *w)
164 {
165 printf("Word %d: %s ", c, w);
166 }
167
168 int queue_word(char *word, shared *s)
169 {
170 entry *e;
171 int current, retval;
172
173 current = (s->last_produced + 1) % QUEUESIZE;
174
175 e = &s->queue[current];
176
177 sem_wait(&e->lock);
178
179 if (e->word[0] != '') {
180 /* consumer hasn't consumed this entry yet */
181 sem_post(&e->lock);
182 wait_for_consumer(s);
183 sem_wait(&e->lock);
184 }
185
186 if (e->word[0] != '') {
187 fprintf(stderr, "ERROR: No room for producer after waiting! ");
188 retval = -1;
189 goto done;
190 } else {
191 strncpy(e->word, word, WORDSIZE);
192 s->last_produced = current;
193 s->prod_count++;
194 wakeup_consumer(s);
195 retval = 0;
196 goto done;
197 }
198
199 done:
200 sem_post(&e->lock);
201 return retval;
202 }
203
204 int get_next_word(char *word, shared *s)
205 {
206 entry *e;
207 int current, retval;
208
209 current = (s->last_consumed + 1) % QUEUESIZE;
210
211 e = &s->queue[current];
212
213 sem_wait(&e->lock);
214
215 if (e->word[0] == '') {
216 /* producer hasn't filled in this entry yet */
217 sem_post(&e->lock);
218 wait_for_producer(s);
219 sem_wait(&e->lock);
220 }
221
222 if (e->word[0] == '') {
223 fprintf(stderr, "ERROR: Nothing for consumer after waiting! ");
224 retval = -1;
225 goto done;
226 } else {
227 strncpy(word, e->word, WORDSIZE);
228 e->word[0] = '';
229 s->last_consumed = current;
230 s->con_count++;
231 wakeup_producer(s);
232 retval = 0;
233 goto done;
234 }
235
236 done:
237 sem_post(&e->lock);
238 return retval;
239 }
240
241 void producer(shared *s, int event_count, int producer_delay_interval)
242 {
243 char word[WORDSIZE];
244 int i;
245 struct sigaction signal_handler_struct;
246
247 memset (&signal_handler_struct, 0, sizeof(signal_handler_struct));
248 signal_handler_struct.sa_handler = producer_handler;
249
250 if (sigaction(SIGUSR1, &signal_handler_struct, NULL)) {
251 fprintf(stderr, "Producer couldn't register SIGUSR1 handler. ");
252 }
253
254 for (i=0; i < event_count; i++) {
255 pick_word(word);
256 queue_word(word, s);
257 if (producer_delay_interval > 0) {
258 if (i % producer_delay_interval == 0) {
259 sleep(1);
260 }
261 }
262 }
263
264 printf("Producer finished. ");
265 exit(0);
266 }
267
268 void consumer(shared *s, int event_count, int consumer_delay_interval)
269 {
270 char word[WORDSIZE];
271 int i;
272 struct sigaction signal_handler_struct;
273
274 memset (&signal_handler_struct, 0, sizeof(signal_handler_struct));
275 signal_handler_struct.sa_handler = consumer_handler;
276
277 if (sigaction(SIGUSR1, &signal_handler_struct, NULL)) {
278 fprintf(stderr, "Consumer couldn't register SIGUSR1 handler. ");
279 }
280
281 for (i=0; i < event_count; i++) {
282 get_next_word(word, s);
283 output_word(s->con_count, word);
284 if (consumer_delay_interval > 0) {
285 if (i % consumer_delay_interval == 0) {
286 sleep(1);
287 }
288 }
289 }
290
291 printf("Consumer finished. ");
292 exit(0);
293 }
294
295 void init_shared(shared *s)
296 {
297 int i;
298
299 s->con_waiting = 0;
300 s->last_consumed = -1;
301
302 s->prod_waiting = 0;
303 s->last_produced = -1;
304
305 s->prod_pid = -1;
306 s->con_pid = -1;
307
308 s->prod_count = 0;
309 s->con_count = 0;
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.