Changeset fe3cd36
- Timestamp:
- Jul 1, 2018, 9:00:30 AM (6 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- 7c919446
- Parents:
- 22cf65e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/papers/concurrency/Paper.tex
r22cf65e rfe3cd36 3 3 \articletype{RESEARCH ARTICLE}% 4 4 5 \received{ 26 April 2016}6 \revised{ 6 June 2016}7 \accepted{ 6 June 2016}5 \received{XXXXX} 6 \revised{XXXXX} 7 \accepted{XXXXX} 8 8 9 9 \raggedbottom … … 948 948 \subsection{Coroutine Implementation} 949 949 950 A significant implementation challenge for coroutines (and threads, see section\ref{threads}) is adding extra fields and executing code after/before the coroutine constructor/destructor and coroutine main to create/initialize/de-initialize/destroy extra fields and the stack.950 A significant implementation challenge for coroutines (and threads, see Section~\ref{threads}) is adding extra fields and executing code after/before the coroutine constructor/destructor and coroutine main to create/initialize/de-initialize/destroy extra fields and the stack. 951 951 There are several solutions to this problem and the chosen option forced the \CFA coroutine design. 952 952 … … 1301 1301 1302 1302 For maximum usability, monitors have \newterm{multi-acquire} semantics allowing a thread to acquire it multiple times without deadlock. 1303 For example, atomically printing the contents of a binary tree: 1304 \begin{cfa} 1305 monitor Tree { 1306 Tree * left, * right; 1307 // value 1308 }; 1309 void print( Tree & mutex tree ) { $\C{// prefix traversal}$ 1310 // write value 1311 print( *tree->left ); $\C{// multiply acquire monitor lock for tree on each recursion}$ 1312 print( *tree->right ); 1313 } 1303 \begin{cfa} 1304 monitor M { ... } m; 1305 void foo( M & mutex m ) { ... } $\C{// acquire mutual exclusion}$ 1306 void bar( M & mutex m ) { $\C{// acquire mutual exclusion}$ 1307 ... `foo( m );` ... $\C{// reacquire mutual exclusion}$ 1308 } 1309 `bar( m );` $\C{// nested monitor call}$ 1314 1310 \end{cfa} 1315 1311 … … 1406 1402 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}} 1407 1403 \begin{cfa} 1408 monitor M { };1404 monitor M { ... }; 1409 1405 void foo( M & mutex m1, M & mutex m2 ) { 1410 1406 // critical section … … 1652 1648 @waitfor@ statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer. 1653 1649 To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible. 1654 1655 1650 % When an overloaded routine appears in an @waitfor@ statement, calls to any routine with that name are accepted. 1656 1651 % The rationale is that members with the same name should perform a similar function, and therefore, all should be eligible to accept a call. 1657 As always, overloaded routines can be disambiguated using a cast:1652 Overloaded routines can be disambiguated using a cast: 1658 1653 \begin{cfa} 1659 1654 void rtn( M & mutex m ); … … 1762 1757 Signalled threads are moved to the urgent queue and the waiter at the front defines the set of monitors necessary for it to unblock. 1763 1758 Partial signalling transfers ownership of monitors to the front waiter. 1764 When the signaller thread exits or waits in the monitor the front waiter is unblocked if all its monitors are released.1765 The benefit of this solutionis encapsulating complexity into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.1759 When the signaller thread exits or waits in the monitor, the front waiter is unblocked if all its monitors are released. 1760 The benefit is encapsulating complexity into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met. 1766 1761 1767 1762 … … 1773 1768 Similarly, monitor routines can be added at any time in \CFA, making it less clear for programmers and more difficult to implement. 1774 1769 \begin{cfa} 1775 monitor M { };1770 monitor M { ... }; 1776 1771 void `f`( M & mutex m ); 1777 1772 void g( M & mutex m ) { waitfor( `f` ); } $\C{// clear which f}$ … … 1819 1814 External scheduling, like internal scheduling, becomes significantly more complex for multi-monitor semantics. 1820 1815 Even in the simplest case, new semantics needs to be established. 1821 \begin{cfa} 1822 monitor M {}; 1816 \newpage 1817 \begin{cfa} 1818 monitor M { ... }; 1823 1819 void f( M & mutex m1 ); 1824 1820 void g( M & mutex m1, M & mutex m2 ) { … … 1833 1829 This behaviour can be extended to the multi-monitor @waitfor@ statement. 1834 1830 \begin{cfa} 1835 monitor M { };1831 monitor M { ... }; 1836 1832 void f( M & mutex m1, M & mutex m2 ); 1837 1833 void g( M & mutex m1, M & mutex m2 ) { … … 2244 2240 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2245 2241 \begin{cfa} 2246 monitor M { } m1/*, m2, m3, m4*/;2242 monitor M { ... } m1/*, m2, m3, m4*/; 2247 2243 void __attribute__((noinline)) do_call( M & mutex m/*, m2, m3, m4*/ ) {} 2248 2244 int main() { … … 2298 2294 volatile int go = 0; 2299 2295 condition c; 2300 monitor M { } m;2296 monitor M { ... } m; 2301 2297 void __attribute__((noinline)) do_call( M & mutex a1 ) { signal( c ); } 2302 2298 thread T {}; … … 2349 2345 \begin{cfa} 2350 2346 volatile int go = 0; 2351 monitor M { } m;2347 monitor M { ... } m; 2352 2348 thread T {}; 2353 2349 void __attribute__((noinline)) do_call( M & mutex ) {}
Note: See TracChangeset
for help on using the changeset viewer.