Changeset 47b7142
- Timestamp:
- Jul 20, 2023, 4:47:06 PM (16 months ago)
- Branches:
- master
- Children:
- d4c1d1f
- Parents:
- c03c1ac
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/colby_parsons_MMAth/text/waituntil.tex
rc03c1ac r47b7142 477 477 \end{tabular} 478 478 \end{cquote} 479 These examples are basically equivalen ce.479 These examples are basically equivalent. 480 480 Here, the multiple timeouts are useful because the durations can change during execution and the separate clauses provide different code blocks if a timeout triggers. 481 481 Multiple timeouts can also be used with @and@ to provide a minimal delay before proceeding. … … 499 499 In either case, after the WUT unblocks it is safe to execute its the corresponding code block knowing access to the resource is protected by the lock or the read-only state of the future. 500 500 Similarly, for channels, when an outside thread inserts a value into a channel, it must unblock the WUT. 501 However, for channels, there is a race issue.502 If the outside thread inserts into the channel and unblocks the WUT, there is a race such that,another thread can remove the channel data, so after the WUT unblocks and attempts to remove from the buffer, it fails, and the WUT must reblock (busy waiting).501 However, for channels, there is a race condition that poses an issue. 502 If the outside thread inserts into the channel and unblocks the WUT, there is a race where another thread can remove the channel data, so after the WUT unblocks and attempts to remove from the buffer, it fails, and the WUT must reblock (busy waiting). 503 503 This scenario is a \gls{toctou} race that needs to be consolidated. 504 504 To close the race, the outside thread must detect this case and insert directly into the left-hand side of the channel expression (@i << chan@) rather than into the channel, and then unblock the WUT. … … 522 522 523 523 It was deemed important that exclusive-or semantics are maintained when only @or@ operators are used, so this situation has been special-cased, and is handled by having all clauses race to set a value \emph{before} operating on the channel. 524 \PAB{explain how this is handled.} 525 526 \PAB{I'm lost here to the end of the section. You have no example of the case you want to discuss so a made something up.} 524 Consider the following example with three threads running concurrently. 525 \begin{cfa} 526 channel A, B; // zero size channels 527 528 // Thread 1: 529 waituntil( i << A ) {} 530 or waituntil( i << B ) {} 531 532 // Thread 2: 533 waituntil( A << 1 ) {} 534 535 // Thread 3: 536 waituntil( B << 2 ) {} 537 \end{cfa} 538 539 For Thread 1 to have exclusive-or semantics, it must only consume from exactly one of @A@ or @B@. 540 As such, Thread 2 and 3 must race to establish the winning clause of the @waituntil@ in Thread 1. 541 This race is consolidated by Thread 2 and 3 each attempting to set a pointer to the winning clause's @select_node@ address using \gls{cas}. 542 The winner will successfully \gls{cas} the address, insert the value and then signal Thread 1, whereas the loser will fail their \gls{cas}. 543 If there is space in the channel, the losing thread may proceed with their channel operation and not signal, otherwise if there is no space they block as they would in a standard channel insert operation. 544 It is important that threads race \emph{before} operating on the channel, since if they lose the race they may need to take a different action with respect to their channel operation. 545 In the example case, the winner will handoff their value to Thread 1 and the loser will block. 546 If the race was consolidated after the operation, both Thread 2 and 3 could potentially write into @i@ concurrently, which would be erroneous behaviour. 527 547 528 548 Channels introduce another interesting consideration in their implementation. 529 Supporting both reading and writing to a channel in a @waituntil@ means that one @waituntil@ clause may be the notifier by another @waituntil@ clause. 530 \begin{cfa} 531 waituntil( i << A ) { @B << i;@ } 532 or waituntil( i << B ) { @A << i;@ } 533 \end{cfa} 549 Supporting both reading and writing to a channel in a @waituntil@ means that one @waituntil@ clause may be the notifier of another @waituntil@ clause. 534 550 This poses a problem when dealing with the special-cased @or@ where the clauses need to win a race to operate on a channel. 535 When both a special-case @or@ is inserting to a channel on one thread and another thread is blocked in a special-case @or@ consuming from the same channel there is not one but two races that need to be consolidated by the inserting thread. 536 (This race can also occur in the mirrored case with a blocked producer and signalling consumer.) 537 For the producing thread to know that the insert succeeded, they need to win the race for their own @waituntil@ and win the race for the other @waituntil@. 551 552 Consider the following example, alongside a described ordering of events to highlight the race. 553 Assume Thread 1 executes first, registers with channel @A@ and proceeds since it is empty and then is interrupted before registering with @B@. 554 Thread 2 similarly registers with channel @B@, and proceeds since it doesn't have space to insert and then is interrupted before registering with @A@. 555 At this point Thread 1 and 2 resume execution. 556 There is now a race that must be dealt with on two fronts. 557 If Thread 1 and 2 only race to \gls{cas} a winning clause for their own @waituntil@, Thread 1 may think that it successfully removed from @B@ and Thread 2 may think it successfully inserted into @A@, when only one of these operations can occur. 558 \begin{cfa} 559 channel A, B; // zero size channels 560 561 // Thread 1: 562 waituntil( i << A ) {} 563 or waituntil( i << B ) {} 564 565 // Thread 2: 566 waituntil( B << 2 ) {} 567 or waituntil( A << 1 ) {} 568 \end{cfa} 538 569 539 570 Go solves this problem in their select statement by acquiring the internal locks of all channels before registering the select on the channels. 540 This eliminates the race s ince no other threads can operate on the blocked channel since its lock is held.571 This eliminates the race shown above since both Thread 1 and 2 cannot both be registering at the same time. 541 572 This approach is not used in \CFA since the @waituntil@ is polymorphic. 542 573 Not all types in a @waituntil@ have an internal lock, and when using non-channel types acquiring all the locks incurs extra unneeded overhead. 543 574 Instead, this race is consolidated in \CFA in two phases by having an intermediate pending status value for the race. 544 This race case is detectable, and if detected, the outside thread first races to set its own race flag to be pending. 545 If it succeeds, it then attempts to set the WUT's race flag to its success value. 546 If the outside thread successfully sets the WUT's race flag, then the operation can proceed, if not the signalling threads set its own race flag back to the initial value. 547 If any other threads attempt to set the producer's flag and see a pending value, they will wait until the value changes before proceeding to ensure that in the case that the producer fails, the signal will not be lost. 575 This race case is detectable, and if detected, each thread first races to set its own @waituntil@ race pointer to be pending. 576 If it succeeds, it then attempts to set the other thread's @waituntil@ race pointer to its success value. 577 If either thread successfully sets the the other thread's @waituntil@ race pointer, then the operation can proceed, if not the signalling threads set its own race pointer back to the initial value and repeats. 578 This retry mechanism can potentially introduce a livelock, but in practice a livelock here is highly unlikely. 579 Furthermore, the likelihood of a livelock here is zero unless the program is in the niche case of having two or more exclusive-or waituntils with 2 or more clauses in reverse order of priority. 580 This livelock case could be fully eliminated using locks like Go, or if a \gls{dcas} instruction is available. 581 If any other threads attempt to set a WUT's race pointer and see a pending value, they will wait until the value changes before proceeding to ensure that in the case that the WUT fails, the signal will not be lost. 548 582 This protocol ensures that signals will not be lost and that the two races can be resolved in a safe manner. 549 583 550 584 Channels in \CFA have exception based shutdown mechanisms that the @waituntil@ statement needs to support. 551 These exception mechanisms were what brought inthe @on_selected@ routine.585 These exception mechanisms are supported through the @on_selected@ routine. 552 586 This routine is needed by channels to detect if they are closed upon waking from a @waituntil@ statement, to ensure that the appropriate behaviour is taken and an exception is thrown. 553 587
Note: See TracChangeset
for help on using the changeset viewer.