Lab overview
Lab 01
Lab 02
Lab 03
Lab 04
Lab 05
Lab 06
Lab 07
Lab 08
Lab 09
Lab 10
Lab 11
Lab 12
Lab 13
Review

[Course home page]

CSC 209 lab 12 exercises, week of 2 August 2022

[solutions are available (requires teach.cs authentication)]

Experiments with concurrency

Attendance

As usual, please either run /u/csc209h/summer/present on the console of a lab workstation during the tutorial, or get the TA to record your attendance. Please do this first so that you don't forget.

Remember that you can check that your attendance has been recorded properly at https://wwwcgi.teach.cs.toronto.edu/~ajr/cgi-bin/auth/present


1. Simultaneous writes

1a) Write a C program which opens a file named "output" (hard-coded — that is, you are literally just calling fopen("output","w")) and writes the argv[1] string to that file a bunch of times — perhaps 50 times to start.

Run it twice at once with a command like "./a.out aaaaa & ./a.out bbbbb".

Which one "wins"? How much do you have to increase the number of lines by to get a file containing some of each output interspersed? (not necessarily reliably)

You might find the program "bfreq" which we used in lab 03 to be helpful in evaluating the "output" file, especially once it gets large.

alias bfreq=/u/csc209h/summer/pub/lab/03/bfreq


1b) Use the flock() function to block until no one else is accessing the file. Does this help? What is happening?

1c) After flock() returns but before writing to the file, seek to the end of the file with "fseek(fp, 0, SEEK_END)". Does this help? What's happening here? Is this a reliable solution?


2. Producer/consumer pipeline (for credit)

See files in /u/csc209h/summer/pub/lab/12/conversation . Experiment with "anagrammer" a bit — just run it interactively and type various words to it. Try "remote" and "demo".

You will write a program to produce input to anagrammer. Your program will be called "speaker.c". It will be linked with wordlist.c. It outputs a random selection from "wordlist" in wordlist.c every second for ten seconds as follows:

  1. At the beginning of the program, open /dev/urandom with the call open("/dev/urandom", O_RDONLY). Save the value which open() returns, as it is a file descriptor you will read() from. But check if it's negative, and if so, call perror("/dev/urandom") and exit.
  2. Loop ten times. Each time around the loop, where 'r' is a variable of type unsigned char (not int) (you don't have to call it "r", but I had to pick something for the explanation), do
    	read(fd, &r, 1)
    
    where fd is the value returned from open at the beginning. 'r' must be unsigned char, not just char. Check that read() returns 1; else this is a fatal error.
    Then r is a random byte (0 to 255). Output word number r % wordlistsize .
  3. Also sleep(1) each time around the loop. Test your program and make sure it outputs one word per second, no faster.
  4. Now try running "speaker | anagrammer". Depending on how you wrote it, anagrammer's responses probably all come out at once after ten seconds. Fix this either by adding "fflush(stdout)" in an appropriate place in speaker.c to empty the output buffer, or by disabling buffering of stdout altogether by putting "setbuf(stdout, NULL)" before any output to stdout.
You will submit speaker.c (but not wordlist.c).


3. Parallel computation (for credit)

You will need the material in shell video 06 to do this part of the lab.

Please see shell scripts 1, 2, 3, and 4 in /u/csc209h/summer/pub/lab/12/computation .
Each one of these performs some sort of calculation. The idea is that some of the calculations are time-consuming, but we have a multi-CPU computer so we want to execute them in parallel.
(The use of "sleep" here is just faking the time-consuming calculation.)

Copy these files to a directory of your own. Write a shell script named "compute" which executes "sh 1", "sh 2", "sh 3", and "sh 4", all in parallel, with their outputs redirected to files named "1-result", "2-result", etc. (For this exercise we will cheat and write files in the current directory.)

After all of the processes have terminated, add the four output values together and output the sum.

The output of your shell script should be just this single number. And try doing

	date; sh compute; date
to make sure that it only takes about five seconds to run (the max of all the running times), not nine seconds (the total of all the running times).

(Note: Your solution should be extremely short. Mine is six lines, although yours doesn't have to be THAT short.)


4. Locking

Recall the "addten" shell program from last week's lecture (towards the end), and its concurrency issues when run multiple times simultaneously. See /u/csc209h/summer/pub/lab/12/addten

4a) Attempt to protect it against concurrency problems with a lock file:

  1. Before getting the value and incrementing it and overwriting file, wait until a file named "lockfile" doesn't exist. Yes, this is busy-waiting, but you can make it a little less terrible by doing "sleep 0.1" in the loop. (Note: Being able to specify non-integers to "sleep" is non-standard, but today we will make use of this GNU extension.)
  2. Then do "touch lockfile" to create it, and then you can safely(?) do the file access and increment.
  3. Once you have done that and can relinquish the lock, do "rm lockfile".

Does this work any better? How well does it protect against concurrency problems? Why is there still an issue?

4b) Examine the C program /u/csc209h/summer/pub/lab/12/makelockfile.c (compiled in /u/csc209h/summer/pub/lab/12/makelockfile)
Its exit status is backwards so that it is convenient to do "while makelockfile"
Use this to do a lock file for addten properly.

Does this work? Why is it so much better than the previous version?

4c) Use the "flock" command-line tool (see "man flock") to do a lock properly without using a custom external C program. (It's still using an external C program, but it's one which "comes with linux".)


Submit

First of all, you must run "/u/csc209h/summer/present", during the tutorial time, on the console of a tutorial lab workstation, or get the TA to mark you as present.

Then, by the end of Friday August 5, submit both speaker.c and compute using the usual 'submit' command, with "assignment" name "lab12". As always, speaker.c must compile with "gcc −Wall" with no error or warning messages.