COMP3000 Operating Systems F23: Tutorial 6
In this tutorial you will be learning about two implementations of the producer-consumer problem, a classic example of a concurrency problem. The class textbook covers concurrency in great detail in Chapters 25-34, and the producer-consumer problem is covered in Chapter 30 (Condition Variables) and Chapter 31 (Semaphores). While you can look at this part of the textbook, note that we will not be covering this material in the same level of detail, as should be clear from this tutorial.
General Instructions (same for all tutorials)
Click on Expand to view.
Tutorials are graded based on participation and effort (so no need to struggle to have the “correct” answers — what matters is the attempts and sufficient thinking reflected in your answers), but you should still turn in your work. Submit your answers on Brightspace as a single text file named "<username>-comp3000-t<n>.txt" (where username is your MyCarletonOne username and n is the tutorial number). The first four lines of this file should be "COMP 3000 Tutorial <n>", your name, student number, and the date of submission. Your submitted answers must at least respond to all the items in the Tasks/Questions section.
The deadline is usually four days after the tutorial date (see the actual deadline on the submission entry). Note that the submission entry is enforced by the system, so you may fail to get the effort marks even if it is one minute past the deadline.
You should also check in with your assigned TA (in person or by responding to a poll if online). Your TA will be your first point of contact when you have questions or encounter any issues during the tutorial session.
You get 1.5 marks for submitting answers that shows your effort and 0.5 for checking in, making this tutorial worth 2 points total.
Read through the instructions before starting your work to get an overall picture. When source files are needed, you can download them by clicking on the hyperlink.
A: Getting Started
Download 3000pc.zip, unpack, and run make to compile 3000pc-fifo and 3000pc-rendezvous.
Try to take this opportunity to read and understand the two programs line by line.
- Note that these programs take 3 arguments each:
- The number of events to process
- The number of events to produce before the producer sleeps for 1 second
- The number of events to consume before the consumer sleeps for 1 second
- Note that these programs take 3 arguments each:
- Run both programs with the same arguments of your choice. Do this a few times with different arguments. Do they behave the same way? Do you notice any differences? (again, no “correct” answers but just play with them and document your observations)
- Repeat the above experiment, this time running each program under strace (with the -f flag to trace children too). Do you notice any difference in the system calls each program makes? Remember to ignore the lines before main() that might be distracting, e.g., start looking around and after the clone() system call.
- You can see there is "#define QUEUESIZE 32" in both programs. Are they actually used? Why (not)?
B: Producer/Consumer with Pipes
- Examine the source code of 3000pc-fifo. Pay attention to the call to pipe(pipefd) on line 192 and make the connection with what has been discussed in the lecture (also look at the man page for pipe(2)). Explain the following:
- How does the consumer receive words to consume?
- How does the producer generate and send words to the consumer?
- Why is the call to srandom(time(NULL)) on line 169 necessary?
- Replace the call to srandom(time(NULL)) on line 169 with srandom(42). What differences do you notice in 3000pc-fifo's behavior?
- Examine the source code of 3000pc-rendezvous. Explain the following:
- What are a few ways that 3000pc-rendezvous is different from 3000pc-fifo?
- What does the call to mmap() on line 347 do (compared to our previous uses of mmap())? How did you figure this out?
- How does the producer notify the consumer that the queue is no longer empty?
- How does the consumer notify the producer that the queue is no longer full?
- What arguments can you provide to make the producer wait for the consumer? Hint: Check the size of the queue.
- What arguments can you provide to make the consumer wait for the producer? (You can disregard the wait at the very beginning as the queue is initially empty)
- Another student tells you that the difference between processes and threads is that processes never share memory, while threads do. Is this statement correct or incorrect? How can the behavior of 3000pc-rendezvous help justify your answer?
- Change the calls to pthread_mutexattr_setpshared() and pthread_condattr_setpshared() (lines 293 and 298) to take 0 instead of 1. How does the behavior or 3000pc-rendezvous change? Does anything break?