Question: What is one way simple way you can modify 3000pc so the consumer consumes as the producer produces, i.e., the producer and the consumer move

What is one way simple way you can modify 3000pc so the consumer consumes as the producer produces, i.e., the producer and the consumer move essentially in lock step? Your modification should not involve sleeping by either the producer or the consumer. Why does your change work? (To do this precisely is hard; to do this approximately involves a change to one line. The approximate solution is sufficient.)

/* 3000pc.c */

2

3

4

5

6

7

8 #include

9 #include

10 #include

11 #include

12 #include

13 #include

14 #include

15 #include

16 #include

17 #include

18 #include

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 ",

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] != '\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] != '\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] == '\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] == '\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] = '\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

312 s->queue[i].word[0] = '\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 }

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!