Changeset f496046 for doc/theses/colby_parsons_MMAth/text/waituntil.tex
- Timestamp:
- Jul 31, 2023, 12:04:38 PM (14 months ago)
- Branches:
- master
- Children:
- d3c3261
- Parents:
- 14c0f7b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/colby_parsons_MMAth/text/waituntil.tex
r14c0f7b rf496046 382 382 More detail on channels and their interaction with @waituntil@ appear in Section~\ref{s:wu_chans}. 383 383 384 The trait is used by having a blocking object return a type that supports the @is_selectable@ trait. 384 The trait can be used directly by having a blocking object support the @is_selectable@ trait, or it can be used indirectly through routines that take the object as an argument. 385 When used indirectly, the object's routine returns a type that supports the @is_selectable@ trait. 385 386 This feature leverages \CFA's ability to overload on return type to select the correct overloaded routine for the @waituntil@ context. 386 A selectable typeis needed for types that want to support multiple operations such as channels that allow both reading and writing.387 Indirect support through routines is needed for types that want to support multiple operations such as channels that allow both reading and writing. 387 388 388 389 \section{\lstinline{waituntil} Implementation} … … 520 521 This work incurs a high cost for signalling threads and heavily increase contention on internal channel locks. 521 522 Furthermore, the @waituntil@ statement is polymorphic and can support resources that do not have internal locks, which also makes this approach infeasible. 522 As such, the exclusive-or semantics islost when using both @and@ and @or@ operators since it cannot be supported without significant complexity and significantly affects @waituntil@ performance.523 As such, the exclusive-or semantics are lost when using both @and@ and @or@ operators since it cannot be supported without significant complexity and significantly affects @waituntil@ performance. 523 524 524 525 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. … … 591 592 If any other threads attempt to set a WUT's race pointer and see a pending value, they wait until the value changes before proceeding to ensure that, in the case the WUT fails, the signal is not lost. 592 593 This protocol ensures that signals cannot be lost and that the two races can be resolved in a safe manner. 593 \PAB{I bet one of the readers is going to ask you to write the pseudo code for this algorithm.} 594 The implementation of this protocol is shown in Figure~\ref{f:WU_DeadlockAvoidance}. 595 596 \begin{figure} 597 \begin{cfa} 598 bool pending_set_other( select_node & other, select_node & mine ) { 599 unsigned long int cmp_status = UNSAT; 600 601 // Try to set other status, if we succeed break and return true 602 while( !CAS( other.clause_status, &cmp_status, SAT ) ) { 603 if ( cmp_status == SAT ) 604 return false; // If other status is SAT we lost so return false 605 606 // Toggle own status flag to allow other thread to potentially win 607 mine.status = UNSAT; 608 609 // Reset compare flag 610 cmp_status = UNSAT; 611 612 // Attempt to set own status flag back to PENDING to retry 613 if ( !CAS( mine.clause_status, &cmp_status, PENDING ) ) 614 return false; // If we fail then we lost so return false 615 616 // Reset compare flag 617 cmp_status = UNSAT; 618 } 619 return true; 620 } 621 \end{cfa} 622 \caption{Exclusive-or \lstinline{waituntil} channel deadlock avoidance protocol} 623 \label{f:WU_DeadlockAvoidance} 624 \end{figure} 594 625 595 626 Channels in \CFA have exception-based shutdown mechanisms that the @waituntil@ statement needs to support. … … 600 631 601 632 It is trivial to check when a synchronous multiplexing utility is done for the or/xor relationship, since any resource becoming available means that the blocked thread can proceed and the @waituntil@ statement is finished. 602 In \uC and \CFA, the \gls{synch_multiplex} mechanism have both an and/or relationship, which make the problem of checking for completion of the statement difficult. 603 \PAB{Show an example of why this is difficult.} 633 In \uC and \CFA, the \gls{synch_multiplex} mechanism have both an and/or relationship, which along with guards, make the problem of checking for completion of the statement difficult. 634 Consider the @waituntil@ in Figure~\ref{f:WU_ComplexPredicate}. 635 When the @waituntil@ thread wakes up, checking if the statement is complete is non-trivial. 636 The predicate that will return if the statement in Figure~\ref{f:WU_ComplexPredicate} is satisfied is the following. 637 \begin{cfa} 638 A && B || C || !GA && B || !GB && A || !GA && !GB && !GC 639 \end{cfa} 640 Which simplifies to: 641 \begin{cfa} 642 ( A || !GA ) && ( B || !GB ) || C || !GA && !GB && !GC 643 \end{cfa} 644 Checking a predicate this large with each iteration is expensive so \uC and \CFA both take steps to simplify checking statement completion. 645 646 \begin{figure} 647 \begin{cfa} 648 when( GA ) waituntil( A ) {} 649 and when( GB ) waituntil( B ) {} 650 or when( GC ) waituntil( C ) {} 651 \end{cfa} 652 \caption{\lstinline{waituntil} with a non-trivial predicate} 653 \label{f:WU_ComplexPredicate} 654 \end{figure} 604 655 605 656 In the \uC @_Select@ statement, this problem is solved by constructing a tree of the resources, where the internal nodes are operators and the leaves are booleans storing the state of each resource. … … 608 659 Once the root of the tree has both subtrees marked as @true@ then the statement is complete. 609 660 As an optimization, when the internal nodes are updated, the subtrees marked as @true@ are pruned and not examined again. 610 To support statement guards in \uC, the tree prunes a branch if the corresponding guard is false. 611 \PAB{Show an example.} 661 To support statement guards in \uC, the tree is modified to remove an internal node if a guard is false to maintain the appropriate predicate representation. 662 An diagram of the tree for the statement in Figure~\ref{f:WU_ComplexPredicate} is shown in Figure~\ref{f:uC_select_tree}, alongside the modification of the tree that occurs when @GA@ is @false@. 663 664 \begin{figure} 665 \begin{center} 666 \input{diagrams/uCpp_select_tree.tikz} 667 \end{center} 668 \caption{\uC select tree modification} 669 \label{f:uC_select_tree} 670 \end{figure} 612 671 613 672 The \CFA @waituntil@ statement blocks a thread until a set of resources have become available that satisfy the underlying predicate. … … 616 675 Leveraging the compiler, a predicate routine is generated per @waituntil@ that when passes the statuses of the resources, returns @true@ when the @waituntil@ is done, and false otherwise. 617 676 To support guards on the \CFA @waituntil@ statement, the status of a resource disabled by a guard is set to a boolean value that ensures that the predicate function behaves as if that resource is no longer part of the predicate. 618 \PAB{Show an example.} 677 The generated code allows the predicate that is checked with each iteration to be simplified to not check guard values. 678 For example, the following would be generated for the @waituntil@ shown in Figure~\ref{f:WU_ComplexPredicate}. 679 \begin{cfa} 680 // statement completion predicate 681 bool check_completion( select_node * nodes ) { 682 return nodes[0].status && nodes[1].status || nodes[2].status; 683 } 684 685 // skip statement if all guards false 686 if ( GA || GB || GC ) { 687 select_node nodes[3]; 688 nodes[0].status = !GA && GB; // A's status 689 nodes[1].status = !GB && GA; // B's status 690 nodes[2].status = !GC; // C's status 691 692 // ... rest of waituntil codegen ... 693 694 } 695 \end{cfa} 619 696 620 697 \uC's @_Select@, supports operators both inside and outside of the \lstinline[language=uC++]{_Select} clauses. 621 698 In the following example, the code blocks run once their corresponding predicate inside the round braces is satisfied. 622 % C_TODO put this is uC++ code style not cfa-style 699 623 700 \begin{lstlisting}[language=uC++,{moredelim=**[is][\color{red}]{@}{@}}] 624 701 Future_ISM<int> A, B, C, D; … … 640 717 however, that opens the potential for livelock. 641 718 Another possibility is to use resource ordering similar to \CFA's @mutex@ statement, but that alone is insufficient, if the resource ordering is not used universally. 642 Additionally, using resource ordering could conflict with other semantics of the @waituntil@ statement.643 For example, consider if the locks in the example must be acquired in the order @D@, @B@, @C@, @A@ because of other @waituntil@ statements.644 \PAB{I don't understand: If all the locks are available, it becomes complex to both respect the ordering of the \lstinline{waituntil} when choosing which code block to run and also respect the lock ordering of \lstinline{D}, \lstinline{B}, \lstinline{C}, \lstinline{A} at the same time.}645 719 One other way this could be implemented is to wait until all resources for a given clause are available before proceeding to acquire them, but this also quickly becomes a poor approach. 646 720 This approach does not work due to \gls{toctou} issues; … … 661 735 \begin{cfa} 662 736 bool when_conditions[N]; 663 for ( node in s ) $\C[3.75in]{// evaluate guards}$737 for ( node in nodes ) $\C[3.75in]{// evaluate guards}$ 664 738 if ( node has guard ) 665 739 when_conditions[node] = node_guard; … … 667 741 when_conditions[node] = true; 668 742 669 select_nodes s[N]; $\C{// declare N select nodes}$ 743 if ( any when_conditions[node] == true ) { 744 745 select_nodes nodes[N]; $\C{// declare N select nodes}$ 670 746 try { 671 for ( node in s ) $\C{// register nodes}$ 672 if ( when_conditions[node] ) 673 register_select( resource, node ); 674 675 // ... set statuses for nodes with when_conditions[node] == false ... 676 677 while ( statement predicate not satisfied) { $\C{// check predicate}$678 679 680 if ( statement predicate is satisfied) break;681 682 683 684 685 686 687 688 747 // ... set statuses for nodes with when_conditions[node] == false ... 748 749 for ( node in nodes ) $\C{// register nodes}$ 750 if ( when_conditions[node] ) 751 register_select( resource, node ); 752 753 while ( !check_completion( nodes ) ) { $\C{// check predicate}$ 754 // block 755 for ( resource in waituntil statement ) { $\C{// run true code blocks}$ 756 if ( check_completion( nodes ) ) break; 757 if ( resource is avail ) 758 try { 759 if( on_selected( resource ) ) $\C{// conditionally run block}$ 760 run code block 761 } finally $\C{// for exception safety}$ 762 unregister_select( resource, node ); $\C{// immediate unregister}$ 763 } 764 } 689 765 } finally { $\C{// for exception safety}$ 690 for ( registered nodes in s ) $\C{// deregister nodes}$766 for ( registered nodes in nodes ) $\C{// deregister nodes}$ 691 767 if ( when_conditions[node] && unregister_select( resource, node ) 692 768 && on_selected( resource ) ) 693 769 run code block $\C{// run code block upon unregister}\CRT$ 770 } 771 694 772 } 695 773 \end{cfa}
Note: See TracChangeset
for help on using the changeset viewer.