Docstoc

Errata for

Document Sample
Errata for Powered By Docstoc
					                                         Errata for

              The Art of Multiprocessor Programming
                              Version of 3 January 2011

In many places, inserted text is highlighted in red.

There are 5 new eps files to replace existing figures. Replace Figure 14.3 with
lazyskiplist-add.eps. Replace Figure 6.5 with lock-free-universal.eps. Replace Figure
10.12 with LockFreeQueue.eps. Replace Figure 15.3 with SimpleTree.eps. Replace
Figure 6.7 with wait-free-universal.eps.

Also, please completely remove Figure 16.8 on page 380 and remove the sentence “Fig.
16.8 shows such a sub-DAG.” In the 5th line from the bottom on page 379.

Table of contents
p. xvi        add item after Bibliography (note page number)
Suggested Ways to Teach                                                                     494

Preface
p. xvii Pearlman -> Perlman
p. xx “all of which are useful in structuring concurrent applications.”

Chapter 1
P3        Include few words => include a few words
P. 3      references the end -> references at the end
          P3: “The hope is that the reader will understand the issues in a way that will later allow
          him or her to apply the lessons learned to specific multiprocessor systems.”
          P3: line 25: the end -> at the end
p. 3      In Section 1.1 in place of "there are many primes between 1 and 109, but hardly
          any between 9x109 and 1010" should say "there are more primes between 1 and
          109 than between 9x109 and 1010"
p. 4      In Fig. 1.1, line 4 should say
             for (int j = (i * block) + 1; j <= (i + 1)* block;
          j++) {
p. 5      Fig.1.3 add 2 more spaces at the start of line 6
p. 11     Second paragraph of Mutual Exclusion bullet: “Initially the can is either up or
          down. Let us say it was down. Then only the pets can go in, and mutual
          exclusion holds.”
p. 18     Replace question 6 with:
          Use Amdahl’s law to answer the following questions:
               Suppose the sequential part of a program accounts for 40% of the
                  program's execution time on a single processor. Find a limit for the
                  overall speedup that can be achieved by running the program on a
                multiprocessor machine.
              Now suppose the sequential part accounts for 30% of the program's
                computation time. Let sn be the program's speedup on n processes,
                assuming the rest of the program is perfectly parallelizable. Your boss
                tells you to double this speedup: the revised program should have
                speedup s'n > sn/2. You advertize for a programmer to replace the
                sequential part with an improved version that runs k times faster. What
                value of k should you require?
              Suppose the sequential part can be sped up three-fold, and when we do
                so, the modified program takes half the time of the original on n
                processors. What fraction of the overall execution time did the sequential
                part account for? Express your answer as a function of n.
P 22      Change “… threads typically” to “…. Threads typically”

Chapter 2
p. 23   Figure 2.3 should be amended as shown:
            public long getAndIncrement() {
                    lock.lock();
                    try {
                          long temp = value;
                          value = temp + 1;
                          return temp;
                    } finally {
                          lock.unlock();
                    }
              }
P 24    “some thread make” => “some thread makes”
p. 25   Pragma 2.3.1: “We explain the reasons in Chapter 3 and Appendix B.”
        P24: change in line 3-4 to: “Let us assume, for simplicity, that each thread repeatedly
        acquires and releases the lock, with other work taking place in the meantime.”
        P25: after "Pragma 2.3.1" replace “read A(v == x)” by “read A(x == v)”.
p. 26   In Fig. 2.5, remove the word "volatile" from line 2.

p. 35   Change

        “Suppose A’s token is on Node 0, and B’s token on Node 1 (so A has the later
        timestamp). For A, the label() method is trivial: it already has the latest
        timestamp, so it does nothing. For B, the label() method “leapfrogs” A’s node by
        jumping from 0 to 2.”

        to

        “Suppose A’s token is on Node 0, and B’s token on Node 1 (so B has the later
        timestamp). For B, the label() method is trivial: it already has the latest
        timestamp, so it does nothing. For A, the label() method “leapfrogs” B’s node by
        jumping from 0 to 2.”
p. 27    In Fig. 2.6, remove the word "volatile" in lines 3 and 4
p. 27    “if one thread runs completely before the other” -> “if one thread never tries to
         get the lock”
p. 29    Fig 2.7 line 13 “level 1” => “level i”
p.43     Fig 2.17 add the following line between 6 & 7
          … // initialize myIndex
p. 44    Exercise 19. Instead of 3n should be O(3n) and instead of n2n should say O(n2n).
p. 48    Fig 3.3 delete line 6
P 48     Line 4 of Fig 3.3: add space “(T[])new” => “(T[]) new”

Chapter 3
p. 54.   First paragraph: “We use the following shorthand: <p.enq(x) A> -> <p.deq(x)
         B> means that any sequential execution must order A's enqueue of x at p before
         B's dequeue of x at p, and so on.”

P 55     Empty Exception should be EmptyException
P.57     Top of page, “shorthand notion" should be "shorthand notation".
P 60     “the cost ... are” => “the cost ... is”
P. 61    "This method must be synchronized to ensure that only one instance is created,
         even if several threads observe instance to be null create new instances."
          Delete "create new instances".
p. 67    "... head is the index of the next slot from which to remove an item, and tail is
         the index of the next slot in which to place an item."

Chapter 4
p.77     In the table of Figure 4.5 in the second line MRMW Boolean Regular should be
         MRSW Boolean Regular.
p.84     In Fig.4.12, add a new line between 22 and 23 Line
            if (i == me) continue;
         In addition, Line 32 should be
              a_table [ 0 ][ i ] = value;
p. 88    Should be “when B’s snapshot was taken before A started its Scan() call”.
p. 91    In Fig 4.21 Line 20 should be “return newCopy[j].snap;
p. 85    figure 4.13
         "Thread 0 reads a_table[0][1] with value t+1."
         Should be a_table[0][0]
P 87     linearizable to) -> linearizable) to
p. 88    2nd last line
         "before A started its update() call" should be "... scan() call".
p. 90    In Fig 4.19 Line 11 should be “stamp = label;”
p. 94    In Exercise 40 “ Does Peterson’s two thread mutual exclusion algorithm work if
         the shared atomic flag registers are replaced by regular registers”.
p. 95.   In Figure 4.23, the comment “N is the total number of threads”
         is incorrect. N is actually the length of the register.
         P95: “If multiple processors call write(), is this register atomic?” Replace
         “atomic” with “safe.”
         P95: “If multiple processors call write(), is this register atomic?” Replace
         “atomic” with “safe.”


Chapter 5
P 100    “The reader will notice that since the decide() method of a given consensus
         object is executed only once by each thread, and that there are a finite
         number of threads, by definition, a lock-free implementation would also be
         wait-free and vice versa.”
         P101: remove the sentence: “A's moves are showed in black, and B's in gray.”
         P104: Caption of figure 5.3: “In the second execution scenario, A moves first, driving
         the protocol to a 0-valent state s’’. “ replace by: “In the second execution scenario, A
         moves first, then B executes one operation, driving the protocol to a 0-valent state s’’.”
P 106    can provide -> can we provide
p. 108   for a threads A -> for a thread A
         P110: “Exercise 72 asks one to justify this claim.”

p 111    figure 5.11, 3: “Assign23 assign2 = new Assign23(NULL)” should
         be “Assign23 assign23 = new Assign23(NULL)”

p 111 figure 5.11, 5: [indentation should match line 6]
         P114: Figure 5.14 line 5 need to add indentation before “propose(value)”.
p 115 figure 5.14, 5: [indentation]
P 117    provides a get() -> provide a get()
         P117: replace “provides” by “provide” and “a get() method is only a convenience, and
         as proved in a homework assignment.” By “a get() method is only a convenience, and
         so it follows that:”
         P119: In the text “We consider the compareAndSet() operation mentioned earlier, a
         synchronization operation supported by several contemporary architectures. (For example, it
         is called CMPXCHG on the Intel PentiumTM). This method is also known in the literature
         as compare-and-swap. compareAndSet() takes two arguments: an expected value and an
         update value.”
         Remove “mentioned earlier” and replace “As noted earlier, compareAndset() takes…” by
         “A compareAndSet() takes…”
         P119: and P120 exercise 59 should read: “The SetAgree class, like the Consensus class,
         provides a decide() method whose call returns a value that was the input of some
         thread’s decide() call. However, unlike the Consensus class, the values returned by
         decide() calls are not required to agree. Instead, these calls may return no more than k
         distinct values. (When k is 1, SetAgree is the same as consensus.) What is the consensus
         number of the SetAgree class when k >1?”
p 121.   In Exercise 65, Replace “provides the same propose() and decide() method as
         consensus” by “provides the same decide() method as consensus”.

Chapter 6
P 127  figure 6.2
       "Invocation" should be "Invoc".
p. 128 figure 6.4 line 21 "current" should be "Node current".
         P129: Figure 6.5 file named lock-free-universal.pdf seems that somehow the fonts for
         the words “next”, “decideNext”, “seq” and “invoc()” are in boldface even though they
         should be the same as for the word “sentinel.”
         P132: (PRINTERS TYPO, appears OK in galley proof file Ch06-P370591 but
         not in printed book) “The value of before.seq 1 mod n+” should be “The value of
         before.seq + 1 mod n”
         P132 and P133: Changes in red “Now imagine that Thread 3 immediately
         announces its node. Then Thread 7 helps to append Thread 3’s node, but again pauses
         immediately after setting Thread 3’s node’s sequence number to 3, but before adding it
         to head[]. Now Thread 3 wakes up. It will not enter the main loop because its node’s
         sequence number is non zero…”
P 131    figure 6.6 line 23 "current" should be "Node current".
p 131    In Figure 6.6 line 12
         Node help = announce[(before.seq + 1) % n];
p 131    In Figure 6.6 line 17
         Node after = before.decideNext.decide(prefer);
         P132: Figure 6.7 caption: similar changes as in text, thread numbers in red
         “Notice that Thread 5’s own entry in the head[] array is not yet set to its
         announced node. Next, Thread 3 announces its node and
         Thread 7 helps to append Thread 3’s node, setting Thread 3’s node’s sequence
         number
         to 3. Now Thread 3 wakes up. It will not enter the main loop because its node’s
         sequence number is non zero….”


p 134  In Figure 6.8 line 12
       Node help = announce[(before.seq + 1) % n];
p. 134 figure 6.8 line 23 "current" should be "Node current".
p 134 In Figure 6.8 line 17
       Node after = before.decideNext.decide(prefer);
p 137    “Exercise 77. Propose a way to fix the universal construction of Figure 6.8 to
         work for objects with nondeterministic sequential specifications.”
         Exercise 82 first line: "made to the lock-free protocol" should be "made to the
         wait-free protocol"

P 135 announced). thread C => announced). Thread C
p. 132 The value of before.seq 1 mod n+" => "The value of (before.seq + 1) mod n”

Chapter 7
p.146    first line of section: "simple TTASLock" should be "TASLock"
p. 148   In Figure7.5 Line 7 should be:
         maxDelay = max;
P149      line -8: the the -> the
p. 153   Fig. 7.9 omit line 6
         P153: Fig. 7.9 line 2 should be “2 AtomicReference<Qnode> tail;
p. 149   the the critical section => the critical section
P. 151   Replace “shows the CLHLock class's fields, constructor, and QNode class” with “shows
         the CLHLock class's fields and constructor”
P 151    its its own => its own
p. 155   Fig. 7.12 replace “queue” in line 5 with “tail”
p. 155   Fig 7.13, change line 33 to
               // wait until successor fills in the next field
p. 157    First paragraph of Section 7.6, the reference to Pragma 8.2.3 should be to Pragma 8.2.2.
p. 157    “field is null, the associated thread has either not acquired the lock or has released it”
          should be “field is null, the associated thread has either not acquired the lock or has not
          released it yet”

p. 161    Enqueues that node in the queue (Line 12) => Enqueues that node in the queue (Line 8)
p. 162    In Fig. 7.21, Line 6 is redundant and can be omitted.
p. 163    In Fig. 7.23, remove Line 4.
p. 165    “the thread-local myPred field” =>“the thread-local myNode field”
p. 165    “node from myPred” =>“node from myNode”
p .174    Exercise 86 should be: (may require rewrap through page 176, please advise)
                  First barrier implementation: We have a counter protected by a test-and-test-and-
                  set lock. Each thread locks the counter, increments it, releases the lock, and spins,
                  rereading the counter until it reaches n

                  Second barrier implementation: We have an n-element array b, all 0. Thread zero
                  sets b[0] to 1. Every thread i, for 0 < i <= n-1, spins until b[i-1] is 1, sets b[i] to 1,
                  and waits until b[i+1] becomes 2, at which point it proceeds to leave the barrier.
                  Thread b[n-1], upon detecting that b[n-1] is 1, sets b[n-1] to 2 and leaves the
                  barrier.

                   Compare (in ten lines) the behavior of these two implementations on a bus-based
                   cache-coherent architecture. Explain which approach you expect will perform
                   better under low load and high load.
p. 175    In Exercise 86, “Second barrier implementation: We have an n-element boolean array b,
          all false. Thread zero sets b[0] to true. Every thread i, for 0 < i <= n, spins until b[i-1]
          is true, sets b[i] to true, and waits until b[n-1] is true”
p. 175    In Exercise 89, Remove “Notice that” and begin with “In the HCLHLock lock…”.
p. 175    Fig 7.33 replace Line 3 with
          AtomicReference<Qnode> tail = new Qnode();
p. 176    Exercise 91: “whether any thread is holding a lock (but does not actually acquire the
          lock)”


Chapter 8
p. 181 In the caption for Fig. 8.4, change

              However, thread D manages to acquire the critical section lock first,
              and so both A and B spin until C leaves the critical section.

         to
              However, thread D manages to acquire the critical section lock first,
              and so both A and B spin until D leaves the critical section.

p 182     The constructor for LockedQueue should be:
            public LockedQueue(int capacity) {
              items = (T[])new Object[capacity];
           }
p.185   In Figure 8.9, line 48 should be:
                    while (readers > 0 || writer) {

        P185: instead of “both synchronize on the mutex and condition fields” should be
        “both synchronize on the lock and condition fields”

p.186. Figure 8.11 should be:
          private class ReadLock implements Lock {
             public void lock() {
                lock.lock();
                try {
                   while (writer) {
                      condition.await();
                   }
                   readAcquires++;
                } finally {
                   lock.unlock();
                }
             }
             public void unlock() {
                lock.lock();
                try {
                   readReleases++;
                   if (readAcquires == readReleases)
                      condition.signalAll();
                } finally {
                   lock.unlock();
                }
             }
          }
       Figure 8.12 should be
          private class WriteLock implements Lock {
             public void lock() {
                lock.lock();
                try {
                   while (writer) {
                      condition.await();
                   }
                   writer = true;
                   while (readAcquires != readReleases) {
                      condition.await();
                   }
                } finally {
                   lock.unlock();
                }
                }
                public void unlock() {
                  writer = false;
                  condition.signalAll();
                }
         }
P 188    Fig 8.13 replace lines 11-23 with
         public void lock() {
            int me = ThreadID.get();
            lock.lock();
            try {
              if (owner == me) {
                holdCount++;
                return;
              }
              while (holdCount != 0) {
                condition.await();
              }
              owner = me;
              holdCount = 1;
            } finally {
              lock.unlock();
            }
          }
P 189    Line 2-3: initialize => initialize

P196:    Heading 9.2, Line 3: “Node<T> class has three fields. The item…”
         change to:
          “Node<T> class has three fields. \footnote{To be consistent with the Java
         memory model these fields and their modifications later in the text will need to
         be volatile, though we ignore this issue here for the sake of brevity.} The item…”
         [If a footnote will fit, please renumber remaining footnotes. If easier to add a
         side-note to avoid rewrap and renumbering, please set that in a box in the left
         margin]
P 197    any any ordered set => any ordered set

Chapter 9
p 204    last line: "harder than in the course-grained" should be "coarse".
P 207    Fig. 9.13, lines 52,53 change

             Entry pred = this.head; // sentinel node;
             Entry curr = pred.next;

         to

             Node pred = this.head; // sentinel node;
             Node curr = pred.next;
         }
p. 209   nodes has been -> node has been
P211     First graph Change
         (Figs. 9.16 and 9.17) to (Figs 9.17 and 9.18)
         (Fig. 9.18) to (Fig. 9.16)
         "as Fig. 9.19 shows" to ""as Fig. 9.20 shows"
P212     Change "the contains method (Fig. 9.20)" to the contains method (Fig. 9.19)"
p. 213. [Can the following be done with rewrap up to page 221-222?]
        Heading 9.8, starting line 7:
        Replace:
               Fig. 9.22 shows a Thread A attempting to add node a between nodes
               predA and currA. It sets a’s next field to currA, and then calls
               compareAndSet() to set predA’s next field to a. If B wants to remove
               currB from the list, it might call CompareAndSet() to set predB’s next
               field to currB’s successor. It is not hard to see that if these two threads
               try to remove these adjacent nodes concurrently, the list would end up
               with b not being removed. A similar situation for a pair of concurrent
               add() and remove() methods is depicted in the upper part of Fig. 9.22.
        with:
               In Fig. 9.22, part (a) shows a Thread A attempting to remove node node
               a while Thread B is adding a node b. Suppose A applies
               compareAndSet() to head.next, while B applies compareAndSet() to
               a.next. The net effect is that a is correctly deleted but b is not added to
               the list. In part (b) of the figure, Thread A attempts to remove a, the first
               node in the list, while B is about to remove b, where a points to b.
               Suppose A applies compareAndSet() to head.next, while B applies
               compareAndSet() to a.next. The net effect is to remove a, but not b.

                 If B wants to remove currB from the list, it might call compareAndSet()
                 to set predB’s next field to currB’s successor. It is not hard to see that if
                 these two threads try to remove these adjacent nodes concurrently, the
                 list would end up with b not being removed. A similar situation for a pair
                 of concurrent add() and remove() methods is depicted in the upper part
                 of Fig. 9.22.
p.201.   Last paragraph: “except for the initial head sentinel node, acquire the lock for a
         node only while holding the lock for its predecessor”
p. 204   [near bottom of page]
         Replace
         "The same distinctions apply to remove(a) calls. A successful call (a present)
         is linearized when the predecessor node is locked (Lines 36 or 42). A
         successful call (a absent) is linearized when the node containing the next
         higher key is locked (Lines 36 or 42). An unsuccessful call (a present) is
         linearized when the node containing a is locked."

         With:

         "The same distinctions apply to remove(a) calls. A successful call (a present)
         is linearized when the predecessor node is locked (Lines 36 or 42). An
         unsuccessful call (a absent) is linearized when the node containing the next
         higher key is locked (Lines 36 or 42)." [delete last sentence in this paragraph]
         p210: Figure 9.18 the indentation starting in line 9 is off, pred.lock should be
         appropriately aligned with the w of the while in line 6 and next lines aligned
         accordingly.
         p211: Remove the paragraph starting with “Logical removals require a small…” and
         ending with “even if its predecessor is logically or physically deleted.”
         p214: Figure 9.22: The LazyList class -> Figure 9.22: The LockFreeList class
         p218: 40 curr = curr.next -> 40 curr = curr.next.getReference()
            is the almost the same
            again as when -> again when
         p219: The Lock-free

P 206    Fig. 9.11 change line 6 from
          while (curr.key <= key) {
         to
          while (curr.key < key) {
p.204    Figure 9.9 caption: ``Because A must lock both head and a, and B must lock
         both a and b, they are guaranteed to conflict on a, forcing one call to wait for the
         other.''
p.217    In Line 16 "calls attemptMark() to mark currA as logically removed (Line 27)"
         should be "uses a compareAndSet() to attempt to mark currA as logically
         removed (Line 27)".
p.217    In Line 20 "If the attemptMark() call fails, remove() starts over." should be
         replaced by "If the compareAndSet() call fails, remove() starts over."
p. 218   In Figure 9.26, Line 27, replace "27 snip = curr.next.attemptMark(succ,true);"
         by "27 snip = curr.next.compareAndSet(succ, succ, false, true);"
         p218, Fig 9.27, line 36: false{} -> false
p. 221   In Exercise 118 “Explain why the following cannot happen…”
p. 217   "It then calls compareAndSet() (Line 10)" => "It then calls compareAndSet()
         (Line 11)"
p.216    paragraph 1 line 4. "The Window class's find() method” => "The find() method”
p. 225   Fig 10.2 replace line 5 with
          volatile head, tail;
p. 226   Fig 10.3, replace line 24 with
         tail.next = tail; tail = e;
         Fig. 10.4, line 48 replace “size.getAndincrement()” with
         “size.getAndDecerement();”
p. 227   Line 3, Replace “notify waiting enqueuers” with “notify waiting dequeuers”
P. 227   Fig 10.5 replace 66 with
         public volatile Node next;

Chapter 10
p. 224 Paragraph 4: “Pools provide different fairness guarantees. They can be first-in-
       first-out (a queue), last-in-first-out (a stack),”
p. 226 Figure 10.4 should be
             public T deq() {
              T result;
               boolean mustWakeEnqueuers = false;
               deqLock.lock();
               try {
                 while (size.get() == 0)
                   notEmptyCondition.await();
                 result = head.next.value;
                 head = head.next;
                 if (size.getAndDecrement() == capacity) {
                   mustWakeEnqueuers = true;
                 }
               } finally {
                 deqLock.unlock();
               }
               if (mustWakeEnqueuers) {
                 enqLock.lock();
                 try {
                   notFullCondition.signalAll();
                 } finally {
                   enqLock.unlock();
                 }
               }
               return result;
             }
         Fig. 10.3, line 24 should be replaced by:
           tail.next = e;
           tail = tail.next;
P.226    Fig. 10.3 Replace “tail.next = tail = e ;” with “tail = e; tail.next = e;”
p. 227   “The deq() method proceeds as follows. It reads the size field to check whether
         the queue is empty. If so, the dequeuer must wait until an item is enqueued.”
p. 228   Paragraph 2: “The dequeuer then decrements size and releases deqLock.”
         p229: 2nd line: decremented by deq() -> incremented by enq()
             3rd line: incremented by enq() -> decremented by deq().
             Change the line that says: “When the field reaches capacity, the threadlocks
         deqLock and adds deqSize to EnqSize.” To say: “When the field reaches
         capacity, the thread …
         adds deqSize to EnqSize, and resets deqSideSize to 0.
         p230, Fig 10.10: if possible add a line 25 with another closing bracket “}” but if
         it’s a problem with layout not crucial
p. 232   In Figure 10.12 “CAS tail” on the right side should be “CAS head.”
p232:    "help"other
p. 233   Last line of 1st graph: “linearized at Line 33” => “linearized at Line 32”
p. 234   In Fig. 10.14, “Threads B and C: enq a, c, and d.”
p. 236   In Fig. 10.15 replace “AtomicReference<T> class” with
         “AtomicStampedReference<T> class”
p. 236   figure 10.16
         delete Line 5.
          p237: the enqueuer then sets -> the enqueuer sets

Chapter 11
p. 246 In paragraph 1, “at which point push()” should be “at which
       point pop()”
p. 246 In Figure 11.1 part (b) the dashed line emanating from top
       should be solid and the solid line directed from top to A should
       be dashed (dashed lines symbolize past states).
          p247: “the throwing of the exception” -> “in Line 3”

          p249: line 2, top of page, "If if fails" should be "If it fails"
          p250: figure 11.6 between lines 30 and 31 need to insert a “}”
          (create new line 31 consisting of "}" set two characters to the left
          of the start of line 30). Then increase current lines 31-43
          numbering by 1 each)
          p255: EliminationArray [118] -> EliminationArray [120]

p. 251 “The waiting thread will consume the item and reset the state to
       EMPTY. Resetting to EMPTY can be done using a simple write”
p. 255 The LockFreeStack is credited to Treiber [145]. The
       EliminationBackoffStack is due to Danny Hendler, Nir Shavit,
       and Lena Yerushalmi.
p254: line 21: calls). -> calls.


Chapter 12
p. 259     “Interestingly, for some data structures based on distributed coordination, high
           throughput does not necessarily mean low latency.”
p. 264     5 lines from the top, “Fig. 12.6” should be “in Part (a) of Fig. 12.3”
p. 261     Add the following first element to the list at the bottom of the page:
            IDLE: This node is not in use.
P 262      Replace “we create a width w=2p array of CNode objects.” with “we create a
           size w \geq p/2 array of CNode objects.”
p. 264     “In Line 20, the thread waits until the locked field is false”
p.264      "For example, Fig 12.6 shows a precombining phase example."
           should be "Fig 12.3".
p. 272     figure 12.11
           "token number 3 enters on wire 2, goes down to wire 1, and ends up on wire 3"
           should be “token number 3 enters on wire 2, goes down to wire 3, and ends up
           on wire 2”

p. 273     In caption of Figure 12.12 Caption first sentence should read “as depicted in
           Fig. 12.11”. In next sentence “The gray Merger[4] network has as inputs the
           even wires coming out of the top Bitonic[4] network, and the odd ones
           from the lower Bitonic[4] network.”

P274       change
         layer[] is an array of width balancers implementing the final network layer.
         The Layer[] array is initialized so that layer[i] and layer[width-i-1] refer to the
         same balancer.

         to

         layer[] is an array of width/2 balancers implementing the final network layer.
         [omit second sentence]
p. 275   Delete sentence
         “The merger[] array is initialized to a Merger network of full width.”
p. 275   In Fig. 12.15, the traverse method is missing a line at the end:
            return (2 * output) + layer[output].traverse();

p.275    figure 12.14
         "Boolean" should be "boolean".
         "traverse(t)" should be "traverse()".
p. 276   In Fig. 12.16, replace Line 17 with:
               return merger.traverse((input >= (size / 2) ?
         (size / 2) : 0) + output);
            }

         p282: “assume inductively that a quiescent Tree[k]”
P. 292   8 lines from the bottom of the page, “Beng-Hong Lim et al.” should be
         “Maurice Herlihy, Beng-Hong Lim, and Nir Shavit”

Chapter 13

p.302     Change Lines 27 and 28 from

              result = table[myBucket].add(x);
              setSize = result ? setSize + 1 : setSize ;

          to
               int myBucket = Math.abs(x.hashCode() % table.length);
               if (! table[myBucket].contains(x)) {
                 table[myBucket].add(x);
                 result = true ;
                 size++ ;
               }


          p312: four lines from bottom “if it it exists”
          p317: and 25, and -> and 23, and

P 313     Fig 3.14 line 2 should be
           static final int HI_MASK = 0x80000000;
p. 313    Figure 13.15 line 22 should be omitted;
p. 314    Fig. 13.16 delete lines 41-42
p. 315    Change “InitialBucket()” to “InitializeBucket()” in the following:

           Fig.13.19 shows the InitialBucket() method,

           InitialBucket() is applied recursively to the parent

          The InitialBucket() method may need to recursively initialize
P 317     Fig 13.22 caption: taken by the values 23 and 25 => taken by the values 3
          and 23
p. 317    Fig. 13.21 should be
          public boolean add(T x) {
             if (contains(x)) {
                return false;
             }
             for (int i = 0; i < LIMIT; i++) {
                if ((x = swap(0, hash0(x), x)) == null) {
                   return true;
                } else if ((x = swap(1, hash1(x), x)) == null) {
                   return true;
                }
             }
             resize();
             Add(x);
          }
          The caption to Fig. 13.22 should say:
                  A sequence of displacements started when an item with key 14 finds
                  both locations Table[0][h0 (14)] and Table[1][h1(14)] taken by the
                  values} 3 and 25, …

p. 319    In caption for Figure 13.24: “… and Table[1][2] below threshold…”
p. 324    “One difference is that the locks[] array has two dimensions.”




Chapter 14
p. 331. Last paragraph: “as in the LazyList class…”
p. 332 Figure 14.3 (b) is wrong. Correct figure is included.
p. 335 “… must become unmarked and fully linked before it can become marked
        (see Fig. 14.7).”
p. 337. In Figure 14.7, Line 102 should be
           if (ismarked ||
p. 340 In caption of Figure 14.9: “Part (b) shows the result of redirecting the dashed
        links.”
p. 343 In Figure 14.11, Line 53 is redundant and can be omitted.
p. 344    In Figure 14.12, Line 87, replace
          “ nodeToRemove.next[level].attemptMark(succ, true);”
          with
          “nodeToRemove.next[level].compareAndSet(succ, succ,
            false, true);”
p. 345    Lines 4 and 5 should end with "applying a compareAndSet()" instead
          of "applying attemptMark()"
p. 345    Each mention of victim should be nodeToRemove.
p. 347    Figure 14.14, Line 145 should read:
           curr = curr.next[ level ]. getReference();
p.353     In Figure 15.3, deleteMin() should be removeMin() in 3 places. *
          figure 15.3 section (d): Third box from left, delete "a" (see SimpleTree.eps)
p. 359. In Figure 15.9 between lines 32 and line 33 add line
         … // other methods omitted



Chapter 15
p. 361 Fig 15.11, lines 77,78, replace

                   heap[bottom].lock();
                   heap[ROOT].lock();
         with
                heap[ROOT].lock();
                heap[bottom].lock();
       Fig 15.11, add the following line between 88 and 89
                heap[ROOT].tag = Status.AVAILABLE;
Fig 15.11, line 108

         replace
                   if (heap[child].score < heap[parent].score {
         with
                   if (heap[child].score < heap[parent].score
                    && heap[child].tag != Status.EMPTY) {


p.353     “If the bins are linearizable, so is SimpleLinear” should say “If the bins are
          quiescently consistent, so is SimpleLinear.”
p.353     In Figure 15.3, “deleteMin()” should be “removeMin()” in 3 places.
p.362     Fig 15.12 (c). Node with the value 10 occurs twice, while node 7 is absent.
p.364     The bottom 10 should be 7 instead (the state before the two swaps).
          In Fig 15.13, drop the curly brackets in Lines 19 and 24, so the lines will read
          If (!curr.marked.get()) {
               if(curr.marked.compareAndSet(false,true))
                  return curr;
               }
             else {
                curr=curr.next[0].getReference();
             }

         p364: new code for the findAndMarkMin procedure in lines 14-27

         public Node<T> findAndMarkMin() {
            Node<T> curr = null;
            curr = head.next[0].getReference();
            while (curr != tail) {
              if (!curr.marked.get()) {
                if (curr.marked.compareAndSet(false, true)) {
                  return curr;
                } else {
                  curr = curr.next[0].getReference();
                }
              }
            }
            return null; // no unmarked nodes
         }




Chapter 16
        p369: a_{ki}\cdot b_{jk} -> a_{ik}\cdot b_{kj}
p. 370 In Fig 16.1, line 5. ymA should be myA
p. 372 Last paragraph, “Line 19” should be “Line 20 of Fig. 16.4”.
p.374 Replace
       53    for (int i = 0; i < 2; i++)
       54          for (int j = 0; j < 2; j++) {
       55                future[i][j][0] =
       56                      exec.submit(new MulTask(aa[i][0], bb[0][i], ll[i][j]));
       57                future[i][j][1] =
       58                      exec.submit(new MulTask(aa[1][i], bb[i][1], rr[i][j]));
       59          }
       With
       53    for (int i = 0; i < 2; i++)
       54          for (int j = 0; j < 2; j++) {
       55                future[i][j][0] =
       56                      exec.submit(new MulTask(aa[i][0], bb[0][j], ll[i][j]));
       57                future[i][j][1] =
       58                      exec.submit(new MulTask(aa[i][1], bb[1][j], rr[i][j]));
       59          }

        p375, Fig 16.6, l8: arg > 2 -> arg >= 2
        p376, Fig 16.7 and p380, Fig 16.8: two of the fib(1) boxes should be named
        fib(0)
        p381: an overloaded task -> an overloaded thread
p. 382 In Fig 16.9, remove line 3
p. 383 In Fig. 16.10, The isEmpty() method should be:
          boolean isEmpty() {
            int localTop = top.getReference();
            int localBottom = bottom;
            return localBottom <= localTop;
          }

         p384: removed a task that is already complete -> stolen a task that has already
         been completed, and removed a task that will never be completed
         p385, Fig 16.12: should the array not extend to place 0?
         [Please add one gray box on top of the stack, left of 0, in both (a) and (b)]
         p386: line 9-10: and the task has been claimed -> and the task has been
         claimed by the caller
         p386, line 12: the the caller
         p386, line 14: only rarely when -> only rarely, when (insert comma where
         indicated)

p. 384 In Figure 16.11 between lines 27 and 28 add a new line with “bottom = 0;”
p. 386 Paragraph 4 should reference corrected Fig. 16.10 (above).
       “On the other hand if bottom is greater than top”
p. 387 2nd paragraph
         "The CircularTaskArray() class" should be "The CircularArray class".
P388      Fig 16.14 line 5 Change
           AtomicReference<Integer> top;;
         to
           AtomicInteger top;

         Line 8 change
            top = new AtomicReference<Integer>(0);
         to
            top = new AtomicInteger(0);

         Fig 16.14 delete line 20

P389     Fig 16.15 delete line 5, in line 5 of first paragraph topfield should be top field.
         p391: that that other threads
p. 393 Exercise 186: “optimized version with T’1 = 1024 seconds, and T’ = 8 seconds.
       Why is it optimized? When you run it on your 32-processor machine, the
       running time is 40 seconds, as predicted by our formula.”
         p395: “two work queues: first, lock the smaller queue, then lock the larger
         queue, and…”


Chapter 17
p. 398   Last paragraph: “This barrier class may look like it works, but it does not.”
p. 399   First paragraph: “Unfortunately, the attempt to make the barrier reusable causes
         it to break”
         Line 13 of figure 17.3 should be
             while (count.get() != 0){};
         p399: balancer's sense field -> barrier's sense field
         p401: $n=r^d$ threads -> $n=r^{d+1}$ threads
         p402: in the last two barriers -> in the last barrier
p. 400   Delete Figure 17.5, and change reference to 17.5 in Pragma to 17.4
P406     “The barrier encompasses an AtomicInteger initialized to n, the number of
         threads.” => “The barrier encompasses an AtomicInteger initialized to 0.”
         “Each thread that becomes active increments the counter (Line 8) and each
         thread that becomes inactive decrements it (Line 10).”

P407     Fig 17.13 change lines 7-11 to
         if (active) {
             count.getAndIncrement();
           } else {
             count.getAndDecrement();
           }

P 411    Exercise 203 should refer to Fig. 17.18

Chapter 18
p. 422   Figs 18.6 and 18.7 are switched with respect to the text.
P 422    “enq(x) call that enqueues that item to another queue q0”
         should be
         “enq(x) call that enqueues that item to another queue q1”
         p422: in last two paragraphs, “Fig 18.6 shows…” should be “Fig. 18.7 shows…”
         and then “Fig. 18.7 shows” should be “Fig. 18.6 shows…”.
         p422: “another queue q0” should be “another queue q1”.
         p423, Fig 18.7, line 3: q1.deq(x) should be q1.enq(x)
         p424: walking though
         p424: search first though

p. 423   figure 18.7 line 3
         "q1.deq(x)" should be "q1.enq(x)".
p. 428   “The doIt() method (line 5 of Figure 18.12) takes…”

p. 428   “Z later reads x, and sees value 2, which is inconsistent with the value it read for
         y.”
p. 429   In Fig. 18.16, Line 3 should be
             protected T internalInit;
p. 430   In Figure 18.17, Line 21 should be
             target.next = next;
p. 433   In Fig. 18.19, line 8 should be
             if (other != previous)
         p433: synchronization., These (change comma to period)
         p435: symmetrically.). (delete extra period inside parens)
         p436: "seqential object" should be "sequential object" (twice, in Fig 18.21 near
         top)
         p436, figure caption, line 2: the a second object

p. 434   “Setters are implemented in a symmetric way, calling the setter in the second
         step.”
          “This class has a single AtomicObject<SSkipNode> field. The constructor
          takes
          as argument values to initialize the AtomicObject<SSkipNode> field.”
          p447: placed in the cache -> placed in the cache line

Appendix A
p. 455    In Fig. A1, Caption should read “This method initializes a number of Java
          threads, starts them, and waits for them to finish.”
P 457     Footnote: Pragma 8.2.3 => Pragma 8.3
p.462     Figure A.5, line 17, comment should be “queue is full”.
p.463     Figure A.6, line 36, comment should be “queue is empty”.
p.466     Last sentence of section should be: “Unlike the Java implementation, is uses two
          different condition variables to wait for the buffer to become either not full or
          not empty.”
          p469: We studied many ways -> We will study many ways


Appendix B
p.473 In Fig. B.4, the right and left-hand sides are reversed.

p.473 change "small memories that are situated closer to the processors and are
      therefore much faster than memory" to "small memories that are situated closer
      to the processors and are therefore much faster than main memory"
      p475: first bullet: cache,. and (replace period with comma)
p.478 “… is not necessarily the order in which they occur in the program.”
      p480: discussed in detail in Chapter 16 -> discussed in detail in Chapter 10
p.480 3rd graf from bottom: “Chapter 16” should be “Chapter 10”
p.481 “John Hennessey and David Patterson”'
         p481: Hennessey -> Hennessy
         p484, in [14]: shared-money -> shared-memory
         p489, in [103]: authors and title are duplicated
         p492, in [142]: Special Issue (10) -> 10(2)
         p496: sense-serving -> sense-reversing
         P499: Index, add entry: Exchanger class 249-251 (between "Events" and
         "Exclusive state")


Back matter
Page 494, immediately following the bibliography, please add the text from the attached
file, "Suggested teaching amendment" on page 494, which is currently blank. Please lay
out to fit on one page only.


Acknowledgements
Page xvii: Please add the following new paragraph at the end:
Thanks to all who have sent us errata to improve this book, including: Rajeev Alur,
Matthew Allen, Liran Barsisa, Igor Berman, Konstantin Boudnik, Bjoern Brandenburg ,
Martin Buchholz, Mario Calha, Michael Champigny, Neill Clift , Eran Cohen, Daniel B.
Curtis, Gil Danziger, Venkat Dhinakaran, David Dice, David Fort, Robert P. Goddard,
Brian Goetz, Bart Golsteijn , K. Gopinath, Jason T. Greene, Dan Grossman, Tim
Halloran, Muhammad Amber Hassaan, Matt Hayes, Francis Hools , Ben Horowitz, Barak
Itkin, Paulo Janotti, Kyungho Jeon, Ahmed Khademzadeh, Irena Karlinsky, Habib Khan,
Omar Khan, Namhyung Kim, Guy Korland , Sergey Kotov, Doug Lea, Yossi Lev, Adam
MacBeth, Adam Morrison, Adam Weinstock, Mike Maloney, Tim McIver, Sergejs
Melderis, Bartosz Milewski, Mark Moir, Adam Morrison, Victor Luchangco, Jose Pedro
Oliveira, Dale Parson, Jonathan Perry, Amir Pnueli, Pat Quillen, Binoy Ravindran , Roei
Raviv, Sudarshan Raghunathan, Jean-Paul Rigault, Michael Rueppel, Mohamed M. Saad,
Assaf Schuster, Marc Shapiro, Nathar Shah, Huang-Ti Shih, Joseph P. Skudlarek, James
Stout, Mark Summerfield, Deqing Sun, Seth Syberg, Fuad Tabba, Binil Thomas, John A
Trono, Thomas Weibel, Adam Weinstock, Jaeheon Yi, Zhenyuan Zhao, Ruiwen Zuo,
Chong Xing

				
DOCUMENT INFO
Categories:
Tags:
Stats:
views:15
posted:12/5/2011
language:English
pages:20