操作系统代写 | INTERLUDE: THREAD API Homework (Code)
In this section, we’ll write some simple multi-threaded programs and
use a speciﬁc tool, called helgrind, to ﬁnd problems in these programs.
Read the README in the homework download for details on how to
build the programs and run helgrind.
1. First build main-race.c. Examine the code so you can see the (hopefully
obvious) data race in the code. Now run helgrind (by typing valgrind
–tool=helgrind main-race) to see how it reports the race. Does it
point to the right lines of code? What other information does it give to you?
2. What happens when you remove one of the offending lines of code? Now
add a lock around one of the updates to the shared variable, and then around
both. What does helgrind report in each of these cases?
3. Now let’s look at main-deadlock.c. Examine the code. This code has a
problem known as deadlock (which we discuss in much more depth in a
forthcoming chapter). Can you see what problem it might have?
4. Now run helgrind on this code. What does helgrind report?
5. Now run helgrind on main-deadlock-global.c. Examine the code;
does it have the same problemthat main-deadlock.c has? Should helgrind
be reporting the same error? What does this tell you about tools like helgrind?
6. Let’s next look at main-signal.c. This code uses a variable (done) to
signal that the child is done and that the parent can now continue. Why is
this code inefﬁcient? (what does the parent end up spending its time doing,
particularly if the child thread takes a long time to complete?)
7. Now run helgrind on this program. What does it report? Is the code
8. Now look at a slightly modiﬁed version of the code, which is found in
main-signal-cv.c. This version uses a condition variable to do the sig-
naling (and associated lock). Why is this code preferred to the previous
version? Is it correctness, or performance, or both?
9. Once again run helgrind on main-signal-cv. Does it report any errors?