Changeset beefc34c


Ignore:
Timestamp:
Jun 7, 2018, 6:12:11 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
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, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, with_gc
Children:
6eb131c, 7b28e4a
Parents:
174845e (diff), 85b1deb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
1 added
2 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/concurrency/Paper.tex

    r174845e rbeefc34c  
    5656\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    5757\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
    58 \newcommand{\R}[1]{\Textbf{#1}}
    59 \newcommand{\B}[1]{{\Textbf[blue]{#1}}}
    60 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    6158\newcommand{\uC}{$\mu$\CC}
    62 \newcommand{\cit}{\textsuperscript{[Citation Needed]}\xspace}
    63 \newcommand{\TODO}{{\Textbf{TODO}}}
     59\newcommand{\TODO}[1]{{\Textbf{#1}}}
    6460
    6561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    258254\section{Introduction}
    259255
    260 This paper provides a minimal concurrency \newterm{Abstract Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
     256This paper provides a minimal concurrency \newterm{Application Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
    261257While the simplest concurrency system is a thread and a lock, this low-level approach is hard to master.
    262258An easier approach for programmers is to support higher-level constructs as the basis of concurrency.
     
    587583As such, library support for threading is far from widespread.
    588584At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
    589 On modern architectures, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
     585In modern programming languages, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
    590586As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages.
    591587Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
     
    625621\newbox\myboxA
    626622\begin{lrbox}{\myboxA}
    627 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     623\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    628624`int f1, f2, state = 1;`   // single global variables
    629625int fib() {
     
    642638        }
    643639}
    644 \end{lstlisting}
     640\end{cfa}
    645641\end{lrbox}
    646642
    647643\newbox\myboxB
    648644\begin{lrbox}{\myboxB}
    649 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     645\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    650646#define FIB_INIT `{ 0, 1 }`
    651647typedef struct { int f2, f1; } Fib;
     
    664660        }
    665661}
    666 \end{lstlisting}
     662\end{cfa}
    667663\end{lrbox}
    668664
     
    677673\newbox\myboxA
    678674\begin{lrbox}{\myboxA}
    679 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     675\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    680676`coroutine` Fib { int fn; };
    681677void main( Fib & fib ) with( fib ) {
     
    697693        }
    698694}
    699 \end{lstlisting}
     695\end{cfa}
    700696\end{lrbox}
    701697\newbox\myboxB
    702698\begin{lrbox}{\myboxB}
    703 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     699\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    704700`coroutine` Fib { int ret; };
    705701void main( Fib & f ) with( fib ) {
     
    721717
    722718
    723 \end{lstlisting}
     719\end{cfa}
    724720\end{lrbox}
    725721\subfloat[3 States, internal variables]{\label{f:Coroutine3States}\usebox\myboxA}
     
    769765\newbox\myboxA
    770766\begin{lrbox}{\myboxA}
    771 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     767\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    772768`coroutine` Format {
    773769        char ch;   // used for communication
     
    801797        }
    802798}
    803 \end{lstlisting}
     799\end{cfa}
    804800\end{lrbox}
    805801
    806802\newbox\myboxB
    807803\begin{lrbox}{\myboxB}
    808 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     804\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    809805struct Format {
    810806        char ch;
     
    838834        format( &fmt );
    839835}
    840 \end{lstlisting}
     836\end{cfa}
    841837\end{lrbox}
    842838\subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
     
    10441040};
    10451041\end{cfa}
    1046 & {\Large $\Rightarrow$} &
     1042&
     1043{\Large $\Rightarrow$}
     1044&
    10471045\begin{tabular}{@{}ccc@{}}
    10481046\begin{cfa}
     
    14451443\label{s:InternalScheduling}
    14461444
    1447 While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed, \eg a bounded buffer, Figure~\ref{f:BoundedBuffer}, may be full/empty so produce/consumer threads must block.
     1445While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed, \eg a bounded buffer, Figure~\ref{f:GenericBoundedBuffer}, may be full/empty so produce/consumer threads must block.
    14481446Leaving the monitor and trying again (busy waiting) is impractical for high-level programming.
    14491447Monitors eliminate busy waiting by providing internal synchronization to schedule threads needing access to the shared data, where the synchronization is blocking (threads are parked) versus spinning.
    14501448The synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling, where \newterm{scheduling} is defined as indicating which thread acquires the critical section next.
    1451 \newterm{Internal scheduling} is characterized by each thread entering the monitor and making an individual decision about proceeding or blocking, while \newterm{external scheduling} is characterized by an entering thread making a decision about proceeding for itself and behalf of other threads attempting entry.
     1449\newterm{Internal scheduling} is characterized by each thread entering the monitor and making an individual decision about proceeding or blocking, while \newterm{external scheduling} is characterized by an entering thread making a decision about proceeding for itself and on behalf of other threads attempting entry.
    14521450
    14531451Figure~\ref{f:BBInt} shows a \CFA bounded-buffer with internal scheduling, where producers/consumers enter the monitor, see the buffer is full/empty, and block on an appropriate condition lock, @full@/@empty@.
     
    14581456\begin{enumerate}
    14591457\item
    1460 The signalling thread leaves immediately, and the signalled thread continues.
     1458The signalling thread returns immediately, and the signalled thread continues.
    14611459\item
    1462 The signalling thread continues and the signalled thread is marked for urgent unblocking at subsequent scheduling points (exit/wait).
     1460The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
    14631461\item
    1464 The signalling thread blocks but is marked for urgrent unblocking and the signalled thread continues.
     1462The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues.
    14651463\end{enumerate}
    14661464The first approach is too restrictive, as it precludes solving a reasonable class of problems (\eg dating service).
    14671465\CFA supports the next two semantics as both are useful.
    14681466Finally, while it is common to store a @condition@ as a field of the monitor, in \CFA, a @condition@ variable can be created/stored independently.
     1467Furthermore, a condition variable is tied to a \emph{group} of monitors on first use (called \newterm{branding}), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
    14691468
    14701469\begin{figure}
     
    14721471\newbox\myboxA
    14731472\begin{lrbox}{\myboxA}
    1474 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     1473\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    14751474forall( otype T ) { // distribute forall
    14761475        monitor Buffer {
     
    14961495        }
    14971496}
    1498 \end{lstlisting}
     1497\end{cfa}
    14991498\end{lrbox}
    15001499
    15011500\newbox\myboxB
    15021501\begin{lrbox}{\myboxB}
    1503 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     1502\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    15041503forall( otype T ) { // distribute forall
    15051504        monitor Buffer {
     
    15251524        }
    15261525}
    1527 \end{lstlisting}
     1526\end{cfa}
    15281527\end{lrbox}
    15291528
     
    15321531\subfloat[External Scheduling]{\label{f:BBExt}\usebox\myboxB}
    15331532\caption{Generic Bounded-Buffer}
    1534 \label{f:BoundedBuffer}
     1533\label{f:GenericBoundedBuffer}
    15351534\end{figure}
    15361535
     
    15381537External scheduling is controlled by the @waitfor@ statement, which atomically blocks the calling thread, releases the monitor lock, and restricts the routine calls that can next acquire mutual exclusion.
    15391538If the buffer is full, only calls to @remove@ can acquire the buffer, and if the buffer is empty, only calls to @insert@ can acquire the buffer.
    1540 Threads making calls to routines that are currently excluded wait outside (externally) of the monitor on a calling queue.
    1541 
    1542 An important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
     1539Threads making calls to routines that are currently excluded block outside (externally) of the monitor on a calling queue, versus blocking on condition queues inside the monitor.
     1540
     1541Both internal and external scheduling extend to multiple monitors in a natural way.
     1542\begin{cfa}
     1543monitor M { `condition e`; ... };
     1544void foo( M & mutex m1, M & mutex m2 ) {
     1545        ... wait( `e` ); ...                                    $\C{// wait( e, m1, m2 )}$
     1546        ... wait( `e, m1` ); ...
     1547        ... wait( `e, m2` ); ...
     1548}
     1549
     1550void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
     1551void rtn$\(_2\)$( M & mutex m1 );
     1552void bar( M & mutex m1, M & mutex m2 ) {
     1553        ... waitfor( `rtn` ); ...                               $\C{// waitfor( rtn\(_1\), m1, m2 )}$
     1554        ... waitfor( `rtn, m1` ); ...                   $\C{// waitfor( rtn\(_2\), m1 )}$
     1555}
     1556\end{cfa}
     1557For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex types in the parameter list, \ie @wait( e, m1, m2 )@.
     1558To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
     1559Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.
     1560Similarly, for @waitfor( rtn, ... )@, the default semantics is to atomically block the acceptor and release all acquired mutex types in the parameter list, \ie @waitfor( rtn, m1, m2 )@.
     1561To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
     1562Waitfor statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer.
     1563To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible.
     1564
     1565Given the ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
     1566\begin{cfa}
     1567void foo( M & mutex m1, M & mutex m2 ) {
     1568        ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
     1569void baz( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
     1570        ... signal( `e` ); ...
     1571\end{cfa}
     1572The @wait@ only releases @m1@ so the signalling thread cannot acquire both @m1@ and @m2@ to  enter @baz@ to get to the @signal@.
     1573While deadlock issues can occur with multiple/nesting acquisition, this issue results from the fact that locks, and by extension monitors, are not perfectly composable.
     1574
     1575Finally, an important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
    15431576If barging is allowed, synchronization between a singller and signallee is difficult, often requiring multiple unblock/block cycles (looping around a wait rechecking if a condition is met).
    1544 \CFA scheduling does \emph{not} have barging, which simplifies synchronization among threads in the monitor.
     1577\begin{quote}
     1578However, we decree that a signal operation be followed immediately by resumption of a waiting program, without possibility of an intervening procedure call from yet a third program.
     1579It is only in this way that a waiting program has an absolute guarantee that it can acquire the resource just released by the signalling program without any danger that a third program will interpose a monitor entry and seize the resource instead.~\cite[p.~550]{Hoare74}
     1580\end{quote}
     1581\CFA scheduling \emph{precludes} barging, which simplifies synchronization among threads in the monitor and increases correctness.
     1582For example, there are no loops in either bounded buffer solution in Figure~\ref{f:GenericBoundedBuffer}.
    15451583Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design and implementation of \CFA concurrency.
    15461584
    1547 Indeed, like the bulk acquire semantics, internal scheduling extends to multiple monitors in a way that is natural to the user but requires additional complexity on the implementation side.
    1548 
    1549 First, here is a simple example of internal scheduling:
    1550 
    1551 \begin{cfa}
    1552 monitor A {
    1553         condition e;
    1554 }
    1555 
    1556 void foo(A& mutex a1, A& mutex a2) {
     1585
     1586\subsection{Barging Prevention}
     1587
     1588Figure~\ref{f:BargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
     1589The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
     1590The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
     1591When the signalling thread reaches the end of the inner @mutex@ statement, it should transfer ownership of @m1@ and @m2@ to the waiting thread to prevent barging into the outer @mutex@ statement by another thread.
     1592However, both the signalling and signalled threads still need monitor @m1@.
     1593
     1594\begin{figure}
     1595\newbox\myboxA
     1596\begin{lrbox}{\myboxA}
     1597\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1598monitor M m1, m2;
     1599condition c;
     1600mutex( m1 ) {
    15571601        ...
    1558         // Wait for cooperation from bar()
    1559         wait(a1.e);
     1602        mutex( m1, m2 ) {
     1603                ... `wait( c )`; // block and release m1, m2
     1604                // m1, m2 acquired
     1605        } // $\LstCommentStyle{\color{red}release m2}$
     1606        // m1 acquired
     1607} // release m1
     1608\end{cfa}
     1609\end{lrbox}
     1610
     1611\newbox\myboxB
     1612\begin{lrbox}{\myboxB}
     1613\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1614
     1615
     1616mutex( m1 ) {
    15601617        ...
    1561 }
    1562 
    1563 void bar(A& mutex a1, A& mutex a2) {
    1564         // Provide cooperation for foo()
    1565         ...
    1566         // Unblock foo
    1567         signal(a1.e);
    1568 }
    1569 \end{cfa}
    1570 
    1571 % ======================================================================
    1572 % ======================================================================
    1573 \subsection{Internal Scheduling - Multi-Monitor}
    1574 % ======================================================================
    1575 % ======================================================================
    1576 It is easy to understand the problem of multi-monitor scheduling using a series of pseudo-code examples.
    1577 Note that for simplicity in the following snippets of pseudo-code, waiting and signalling is done using an implicit condition variable, like Java built-in monitors.
    1578 Indeed, @wait@ statements always use the implicit condition variable as parameters and explicitly name the monitors (A and B) associated with the condition.
    1579 Note that in \CFA, condition variables are tied to a \emph{group} of monitors on first use (called branding), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
    1580 The example below shows the simple case of having two threads (one for each column) and a single monitor A.
    1581 
    1582 \begin{multicols}{2}
    1583 thread 1
    1584 \begin{cfa}
    1585 acquire A
    1586         wait A
    1587 release A
    1588 \end{cfa}
    1589 
    1590 \columnbreak
    1591 
    1592 thread 2
    1593 \begin{cfa}
    1594 acquire A
    1595         signal A
    1596 release A
    1597 \end{cfa}
    1598 \end{multicols}
    1599 One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling.
    1600 It is important to note here that both @wait@ and @signal@ must be called with the proper monitor(s) already acquired.
    1601 This semantic is a logical requirement for barging prevention.
    1602 
    1603 A direct extension of the previous example is a bulk acquire version:
    1604 \begin{multicols}{2}
    1605 \begin{cfa}
    1606 acquire A & B
    1607         wait A & B
    1608 release A & B
    1609 \end{cfa}
    1610 \columnbreak
    1611 \begin{cfa}
    1612 acquire A & B
    1613         signal A & B
    1614 release A & B
    1615 \end{cfa}
    1616 \end{multicols}
    1617 \noindent This version uses bulk acquire (denoted using the {\sf\&} symbol), but the presence of multiple monitors does not add a particularly new meaning.
    1618 Synchronization happens between the two threads in exactly the same way and order.
    1619 The only difference is that mutual exclusion covers a group of monitors.
    1620 On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
    1621 
    1622 While deadlock issues can occur when nesting monitors, these issues are only a symptom of the fact that locks, and by extension monitors, are not perfectly composable.
    1623 For monitors, a well-known deadlock problem is the Nested Monitor Problem~\cite{Lister77}, which occurs when a @wait@ is made by a thread that holds more than one monitor.
    1624 For example, the following cfa-code runs into the nested-monitor problem:
    1625 \begin{multicols}{2}
    1626 \begin{cfa}
    1627 acquire A
    1628         acquire B
    1629                 wait B
    1630         release B
    1631 release A
    1632 \end{cfa}
    1633 
    1634 \columnbreak
    1635 
    1636 \begin{cfa}
    1637 acquire A
    1638         acquire B
    1639                 signal B
    1640         release B
    1641 release A
    1642 \end{cfa}
    1643 \end{multicols}
    1644 \noindent The @wait@ only releases monitor @B@ so the signalling thread cannot acquire monitor @A@ to get to the @signal@.
    1645 Attempting release of all acquired monitors at the @wait@ introduces a different set of problems, such as releasing monitor @C@, which has nothing to do with the @signal@.
    1646 
    1647 However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly.
    1648 For example, the next cfa-code snippet acquires monitors {\sf A} then {\sf B} before waiting, while only acquiring {\sf B} when signalling, effectively avoiding the Nested Monitor Problem~\cite{Lister77}.
    1649 
    1650 \begin{multicols}{2}
    1651 \begin{cfa}
    1652 acquire A
    1653         acquire B
    1654                 wait B
    1655         release B
    1656 release A
    1657 \end{cfa}
    1658 
    1659 \columnbreak
    1660 
    1661 \begin{cfa}
    1662 
    1663 acquire B
    1664         signal B
    1665 release B
    1666 
    1667 \end{cfa}
    1668 \end{multicols}
    1669 
    1670 \noindent However, this simple refactoring may not be possible, forcing more complex restructuring.
    1671 
    1672 % ======================================================================
    1673 % ======================================================================
    1674 \subsection{Internal Scheduling - In Depth}
    1675 % ======================================================================
    1676 % ======================================================================
    1677 
    1678 A larger example is presented to show complex issues for bulk acquire and its implementation options are analyzed.
    1679 Figure~\ref{f:int-bulk-cfa} shows an example where bulk acquire adds a significant layer of complexity to the internal signalling semantics, and listing \ref{f:int-bulk-cfa} shows the corresponding \CFA code to implement the cfa-code in listing \ref{f:int-bulk-cfa}.
    1680 For the purpose of translating the given cfa-code into \CFA-code, any method of introducing a monitor is acceptable, \eg @mutex@ parameters, global variables, pointer parameters, or using locals with the @mutex@ statement.
    1681 
    1682 \begin{figure}
    1683 \begin{multicols}{2}
    1684 Waiting thread
    1685 \begin{cfa}[numbers=left]
    1686 acquire A
    1687         // Code Section 1
    1688         acquire A & B
    1689                 // Code Section 2
    1690                 wait A & B
    1691                 // Code Section 3
    1692         release A & B
    1693         // Code Section 4
    1694 release A
    1695 \end{cfa}
    1696 \columnbreak
    1697 Signalling thread
    1698 \begin{cfa}[numbers=left, firstnumber=10,escapechar=|]
    1699 acquire A
    1700         // Code Section 5
    1701         acquire A & B
    1702                 // Code Section 6
    1703                 |\label{line:signal1}|signal A & B
    1704                 // Code Section 7
    1705         |\label{line:releaseFirst}|release A & B
    1706         // Code Section 8
    1707 |\label{line:lastRelease}|release A
    1708 \end{cfa}
    1709 \end{multicols}
    1710 \begin{cfa}[caption={Internal scheduling with bulk acquire},label={f:int-bulk-cfa}]
    1711 \end{cfa}
    1712 \begin{center}
    1713 \begin{cfa}[xleftmargin=.4\textwidth]
    1714 monitor A a;
    1715 monitor B b;
    1716 condition c;
    1717 \end{cfa}
    1718 \end{center}
    1719 \begin{multicols}{2}
    1720 Waiting thread
    1721 \begin{cfa}
    1722 mutex(a) {
    1723         // Code Section 1
    1724         mutex(a, b) {
    1725                 // Code Section 2
    1726                 wait(c);
    1727                 // Code Section 3
    1728         }
    1729         // Code Section 4
    1730 }
    1731 \end{cfa}
    1732 \columnbreak
    1733 Signalling thread
    1734 \begin{cfa}
    1735 mutex(a) {
    1736         // Code Section 5
    1737         mutex(a, b) {
    1738                 // Code Section 6
    1739                 signal(c);
    1740                 // Code Section 7
    1741         }
    1742         // Code Section 8
    1743 }
    1744 \end{cfa}
    1745 \end{multicols}
    1746 \begin{cfa}[caption={Equivalent \CFA code for listing \ref{f:int-bulk-cfa}},label={f:int-bulk-cfa}]
    1747 \end{cfa}
    1748 \begin{multicols}{2}
    1749 Waiter
    1750 \begin{cfa}[numbers=left]
    1751 acquire A
    1752         acquire A & B
    1753                 wait A & B
    1754         release A & B
    1755 release A
    1756 \end{cfa}
    1757 
    1758 \columnbreak
    1759 
    1760 Signaller
    1761 \begin{cfa}[numbers=left, firstnumber=6,escapechar=|]
    1762 acquire A
    1763         acquire A & B
    1764                 signal A & B
    1765         release A & B
    1766         |\label{line:secret}|// Secretly keep B here
    1767 release A
    1768 // Wakeup waiter and transfer A & B
    1769 \end{cfa}
    1770 \end{multicols}
    1771 \begin{cfa}[caption={Figure~\ref{f:int-bulk-cfa}, with delayed signalling comments},label={f:int-secret}]
    1772 \end{cfa}
     1618        mutex( m1, m2 ) {
     1619                ... `signal( c )`; ...
     1620                // m1, m2 acquired
     1621        } // $\LstCommentStyle{\color{red}release m2}$
     1622        // m1 acquired
     1623} // release m1
     1624\end{cfa}
     1625\end{lrbox}
     1626
     1627\newbox\myboxC
     1628\begin{lrbox}{\myboxC}
     1629\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1630
     1631
     1632mutex( m1 ) {
     1633        ... `wait( c )`; ...
     1634        // m1 acquired
     1635} // $\LstCommentStyle{\color{red}release m1}$
     1636
     1637
     1638
     1639
     1640\end{cfa}
     1641\end{lrbox}
     1642
     1643\begin{cquote}
     1644\subfloat[Waiting Thread]{\label{f:WaitingThread}\usebox\myboxA}
     1645\hspace{2\parindentlnth}
     1646\subfloat[Signalling Thread]{\label{f:SignallingThread}\usebox\myboxB}
     1647\hspace{2\parindentlnth}
     1648\subfloat[Other Waiting Thread]{\label{f:SignallingThread}\usebox\myboxC}
     1649\end{cquote}
     1650\caption{Barging Prevention}
     1651\label{f:BargingPrevention}
    17731652\end{figure}
    17741653
    1775 The complexity begins at code sections 4 and 8 in listing \ref{f:int-bulk-cfa}, which are where the existing semantics of internal scheduling needs to be extended for multiple monitors.
    1776 The root of the problem is that bulk acquire is used in a context where one of the monitors is already acquired, which is why it is important to define the behaviour of the previous cfa-code.
    1777 When the signaller thread reaches the location where it should ``release @A & B@'' (listing \ref{f:int-bulk-cfa} line \ref{line:releaseFirst}), it must actually transfer ownership of monitor @B@ to the waiting thread.
    1778 This ownership transfer is required in order to prevent barging into @B@ by another thread, since both the signalling and signalled threads still need monitor @A@.
    1779 There are three options:
    1780 
    1781 \subsubsection{Delaying Signals}
    17821654The obvious solution to the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred.
    17831655It can be argued that that moment is when the last lock is no longer needed, because this semantics fits most closely to the behaviour of single-monitor scheduling.
     
    17921664Depending on the order of signals (listing \ref{f:dependency} line \ref{line:signal-ab} and \ref{line:signal-a}) two cases can happen:
    17931665
     1666\begin{comment}
    17941667\paragraph{Case 1: thread $\alpha$ goes first.} In this case, the problem is that monitor @A@ needs to be passed to thread $\beta$ when thread $\alpha$ is done with it.
    17951668\paragraph{Case 2: thread $\beta$ goes first.} In this case, the problem is that monitor @B@ needs to be retained and passed to thread $\alpha$ along with monitor @A@, which can be done directly or possibly using thread $\beta$ as an intermediate.
     
    18011674In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means knowing when to release a group becomes complex and inefficient (see next section) and therefore effectively precludes this approach.
    18021675
     1676
    18031677\subsubsection{Dependency graphs}
    1804 
    18051678
    18061679\begin{figure}
     
    18811754
    18821755\subsubsection{Partial Signalling} \label{partial-sig}
     1756\end{comment}
     1757
    18831758Finally, the solution that is chosen for \CFA is to use partial signalling.
    18841759Again using listing \ref{f:int-bulk-cfa}, the partial signalling solution transfers ownership of monitor @B@ at lines \ref{line:signal1} to the waiter but does not wake the waiting thread since it is still using monitor @A@.
     
    18951770\end{itemize}
    18961771
    1897 % ======================================================================
    1898 % ======================================================================
     1772
    18991773\subsection{Signalling: Now or Later}
    1900 % ======================================================================
    1901 % ======================================================================
    1902 \begin{table}
    1903 \begin{tabular}{|c|c|}
    1904 @signal@ & @signal_block@ \\
    1905 \hline
    1906 \begin{cfa}[tabsize=3]
    1907 monitor DatingService {
    1908         // compatibility codes
    1909         enum{ CCodes = 20 };
    1910 
    1911         int girlPhoneNo
    1912         int boyPhoneNo;
     1774
     1775\begin{figure}
     1776\centering
     1777\newbox\myboxA
     1778\begin{lrbox}{\myboxA}
     1779\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1780enum { CCodes = 20 };
     1781monitor DS {
     1782        int GirlPhNo, BoyPhNo;
     1783        condition Girls[CCodes], Boys[CCodes];
     1784        condition exchange;
    19131785};
    1914 
    1915 condition girls[CCodes];
    1916 condition boys [CCodes];
    1917 condition exchange;
    1918 
    1919 int girl(int phoneNo, int cfa) {
    1920         // no compatible boy ?
    1921         if(empty(boys[cfa])) {
    1922                 wait(girls[cfa]);               // wait for boy
    1923                 girlPhoneNo = phoneNo;          // make phone number available
    1924                 signal(exchange);               // wake boy from chair
     1786int girl( DS & mutex ds, int phNo, int ccode ) {
     1787        if ( is_empty( Boys[ccode] ) ) {
     1788                wait( Girls[ccode] );
     1789                GirlPhNo = phNo;
     1790                exchange.signal();
    19251791        } else {
    1926                 girlPhoneNo = phoneNo;          // make phone number available
    1927                 signal(boys[cfa]);              // wake boy
    1928                 wait(exchange);         // sit in chair
    1929         }
    1930         return boyPhoneNo;
    1931 }
    1932 int boy(int phoneNo, int cfa) {
    1933         // same as above
    1934         // with boy/girl interchanged
    1935 }
    1936 \end{cfa}&\begin{cfa}[tabsize=3]
    1937 monitor DatingService {
    1938 
    1939         enum{ CCodes = 20 };    // compatibility codes
    1940 
    1941         int girlPhoneNo;
    1942         int boyPhoneNo;
     1792                GirlPhNo = phNo;
     1793                signal( Boys[ccode] );
     1794                exchange.wait();
     1795        } // if
     1796        return BoyPhNo;
     1797}
     1798int boy( DS & mutex ds, int phNo, int ccode ) {
     1799        // as above with boy/girl interchanged
     1800}
     1801\end{cfa}
     1802\end{lrbox}
     1803
     1804\newbox\myboxB
     1805\begin{lrbox}{\myboxB}
     1806\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1807
     1808monitor DS {
     1809        int GirlPhNo, BoyPhNo;
     1810        condition Girls[CCodes], Boys[CCodes];
     1811
    19431812};
    1944 
    1945 condition girls[CCodes];
    1946 condition boys [CCodes];
    1947 // exchange is not needed
    1948 
    1949 int girl(int phoneNo, int cfa) {
    1950         // no compatible boy ?
    1951         if(empty(boys[cfa])) {
    1952                 wait(girls[cfa]);               // wait for boy
    1953                 girlPhoneNo = phoneNo;          // make phone number available
    1954                 signal(exchange);               // wake boy from chair
     1813int girl( DS & mutex ds, int phNo, int ccode ) {
     1814        if ( is_empty( Boys[ccode] ) ) { // no compatible
     1815                wait( Girls[ccode] ); // wait for boy
     1816                GirlPhNo = phNo; // make phone number available
     1817
    19551818        } else {
    1956                 girlPhoneNo = phoneNo;          // make phone number available
    1957                 signal_block(boys[cfa]);                // wake boy
    1958 
    1959                 // second handshake unnecessary
    1960 
    1961         }
    1962         return boyPhoneNo;
    1963 }
    1964 
    1965 int boy(int phoneNo, int cfa) {
    1966         // same as above
    1967         // with boy/girl interchanged
    1968 }
    1969 \end{cfa}
    1970 \end{tabular}
    1971 \caption{Dating service example using \protect\lstinline|signal| and \protect\lstinline|signal_block|. }
    1972 \label{tbl:datingservice}
    1973 \end{table}
     1819                GirlPhNo = phNo; // make phone number available
     1820                signal_block( Boys[ccode] ); // restart boy
     1821
     1822        } // if
     1823        return BoyPhNo;
     1824}
     1825int boy( DS & mutex ds, int phNo, int ccode ) {
     1826        // as above with boy/girl interchanged
     1827}
     1828\end{cfa}
     1829\end{lrbox}
     1830
     1831\subfloat[\lstinline@signal@]{\label{f:DatingSignal}\usebox\myboxA}
     1832\qquad
     1833\subfloat[\lstinline@signal_block@]{\label{f:DatingSignalBlock}\usebox\myboxB}
     1834\caption{Dating service. }
     1835\label{f:Dating service}
     1836\end{figure}
     1837
    19741838An important note is that, until now, signalling a monitor was a delayed operation.
    19751839The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the @signal@ statement.
     
    19881852% ======================================================================
    19891853An alternative to internal scheduling is external scheduling (see Table~\ref{tbl:sched}).
     1854
     1855\begin{comment}
    19901856\begin{table}
    19911857\begin{tabular}{|c|c|c|}
     
    20511917\label{tbl:sched}
    20521918\end{table}
     1919\end{comment}
     1920
    20531921This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
    20541922Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
  • src/Common/SemanticError.cc

    r174845e rbeefc34c  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 16 15:01:20 2018
    13 // Update Count     : 9
     12// Last Modified On : Thu Jun  7 08:05:26 2018
     13// Update Count     : 10
    1414//
    1515
     
    9797void SemanticError( CodeLocation location, std::string error ) {
    9898        SemanticErrorThrow = true;
    99         throw SemanticErrorException(location, error);
     99        throw SemanticErrorException( location, error );
    100100}
    101101
  • src/Parser/DeclarationNode.cc

    r174845e rbeefc34c  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 22 08:39:29 2018
    13 // Update Count     : 1074
     12// Last Modified On : Thu Jun  7 12:08:55 2018
     13// Update Count     : 1079
    1414//
    1515
     
    174174}
    175175
    176 DeclarationNode * DeclarationNode::newFunction( string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
     176DeclarationNode * DeclarationNode::newFunction( const string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
    177177        DeclarationNode * newnode = new DeclarationNode;
    178178        newnode->name = name;
     
    245245} // DeclarationNode::newForall
    246246
    247 DeclarationNode * DeclarationNode::newFromTypedef( string * name ) {
     247DeclarationNode * DeclarationNode::newFromTypedef( const string * name ) {
    248248        DeclarationNode * newnode = new DeclarationNode;
    249249        newnode->type = new TypeData( TypeData::SymbolicInst );
     
    268268} // DeclarationNode::newAggregate
    269269
    270 DeclarationNode * DeclarationNode::newEnum( string * name, DeclarationNode * constants, bool body ) {
     270DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body ) {
    271271        assert( name );
    272272        DeclarationNode * newnode = new DeclarationNode;
     
    278278} // DeclarationNode::newEnum
    279279
    280 DeclarationNode * DeclarationNode::newEnumConstant( string * name, ExpressionNode * constant ) {
     280DeclarationNode * DeclarationNode::newEnumConstant( const string * name, ExpressionNode * constant ) {
    281281        DeclarationNode * newnode = new DeclarationNode;
    282282        newnode->name = name;
     
    285285} // DeclarationNode::newEnumConstant
    286286
    287 DeclarationNode * DeclarationNode::newName( string * name ) {
     287DeclarationNode * DeclarationNode::newName( const string * name ) {
    288288        DeclarationNode * newnode = new DeclarationNode;
    289289        newnode->name = name;
     
    291291} // DeclarationNode::newName
    292292
    293 DeclarationNode * DeclarationNode::newFromTypeGen( string * name, ExpressionNode * params ) {
     293DeclarationNode * DeclarationNode::newFromTypeGen( const string * name, ExpressionNode * params ) {
    294294        DeclarationNode * newnode = new DeclarationNode;
    295295        newnode->type = new TypeData( TypeData::SymbolicInst );
     
    300300} // DeclarationNode::newFromTypeGen
    301301
    302 DeclarationNode * DeclarationNode::newTypeParam( TypeClass tc, string * name ) {
     302DeclarationNode * DeclarationNode::newTypeParam( TypeClass tc, const string * name ) {
    303303        DeclarationNode * newnode = new DeclarationNode;
    304304        newnode->type = nullptr;
     
    331331} // DeclarationNode::newTraitUse
    332332
    333 DeclarationNode * DeclarationNode::newTypeDecl( string * name, DeclarationNode * typeParams ) {
     333DeclarationNode * DeclarationNode::newTypeDecl( const string * name, DeclarationNode * typeParams ) {
    334334        DeclarationNode * newnode = new DeclarationNode;
    335335        newnode->name = name;
     
    406406} // DeclarationNode::newBuiltinType
    407407
    408 DeclarationNode * DeclarationNode::newAttr( string * name, ExpressionNode * expr ) {
     408DeclarationNode * DeclarationNode::newAttr( const string * name, ExpressionNode * expr ) {
    409409        DeclarationNode * newnode = new DeclarationNode;
    410410        newnode->type = nullptr;
     
    415415}
    416416
    417 DeclarationNode * DeclarationNode::newAttr( string * name, DeclarationNode * type ) {
     417DeclarationNode * DeclarationNode::newAttr( const string * name, DeclarationNode * type ) {
    418418        DeclarationNode * newnode = new DeclarationNode;
    419419        newnode->type = nullptr;
     
    424424}
    425425
    426 DeclarationNode * DeclarationNode::newAttribute( string * name, ExpressionNode * expr ) {
     426DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
    427427        DeclarationNode * newnode = new DeclarationNode;
    428428        newnode->type = nullptr;
     
    545545                                        type->aggregate.params->appendList( q->type->forall ); // augment forall qualifier
    546546                                } else {                                                                // not polymorphic
    547                                         type->aggregate.params = q->type->forall; // make polymorphic type
    548                                         // change implicit typedef from TYPEDEFname to TYPEGENname
    549                                         typedefTable.changeKind( *type->aggregate.name, TYPEGENname );
     547                                        type->aggregate.params = q->type->forall; // set forall qualifier
    550548                                } // if
    551549                        } else {                                                                        // not polymorphic
  • src/Parser/ParseNode.h

    r174845e rbeefc34c  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  4 22:21:04 2018
    13 // Update Count     : 832
     12// Last Modified On : Wed Jun  6 16:17:18 2018
     13// Update Count     : 843
    1414//
    1515
     
    7777
    7878        ParseNode * next = nullptr;
    79         std::string * name = nullptr;
     79        const std::string * name = nullptr;
    8080        CodeLocation location = yylloc;
    8181}; // ParseNode
     
    171171};
    172172
    173 Expression * build_constantInteger( std::string &str );
    174 Expression * build_constantFloat( std::string &str );
    175 Expression * build_constantChar( std::string &str );
    176 Expression * build_constantStr( std::string &str );
     173Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
     174Expression * build_constantFloat( std::string & str );
     175Expression * build_constantChar( std::string & str );
     176Expression * build_constantStr( std::string & str );
    177177Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
    178178Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
     
    230230        static DeclarationNode * newBuiltinType( BuiltinType );
    231231        static DeclarationNode * newForall( DeclarationNode * );
    232         static DeclarationNode * newFromTypedef( std::string * );
    233         static DeclarationNode * newFunction( std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
     232        static DeclarationNode * newFromTypedef( const std::string * );
     233        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    234234        static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    235         static DeclarationNode * newEnum( std::string * name, DeclarationNode * constants, bool body );
    236         static DeclarationNode * newEnumConstant( std::string * name, ExpressionNode * constant );
    237         static DeclarationNode * newName( std::string * );
    238         static DeclarationNode * newFromTypeGen( std::string *, ExpressionNode * params );
    239         static DeclarationNode * newTypeParam( TypeClass, std::string * );
     235        static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body );
     236        static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
     237        static DeclarationNode * newName( const std::string * );
     238        static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
     239        static DeclarationNode * newTypeParam( TypeClass, const std::string * );
    240240        static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
    241241        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    242         static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
     242        static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );
    243243        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    244244        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
     
    247247        static DeclarationNode * newTuple( DeclarationNode * members );
    248248        static DeclarationNode * newTypeof( ExpressionNode * expr );
    249         static DeclarationNode * newAttr( std::string *, ExpressionNode * expr ); // @ attributes
    250         static DeclarationNode * newAttr( std::string *, DeclarationNode * type ); // @ attributes
    251         static DeclarationNode * newAttribute( std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
     249        static DeclarationNode * newAttr( const std::string *, ExpressionNode * expr ); // @ attributes
     250        static DeclarationNode * newAttr( const std::string *, DeclarationNode * type ); // @ attributes
     251        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    252252        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
    253253        static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
  • src/Parser/TypeData.cc

    r174845e rbeefc34c  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 26 13:46:07 2018
    13 // Update Count     : 603
     12// Last Modified On : Wed Jun  6 17:40:33 2018
     13// Update Count     : 604
    1414//
    1515
     
    610610
    611611                if ( td->basictype == DeclarationNode::Float80 || td->basictype == DeclarationNode::Float128 ) {
    612                         if ( td->complextype != DeclarationNode::NoComplexType ) {
    613                                 genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
    614                         }
     612                        // if ( td->complextype != DeclarationNode::NoComplexType ) {
     613                        //      genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
     614                        // }
    615615                        if ( td->basictype == DeclarationNode::Float80 ) ret = BasicType::Float80;
    616616                        else ret = BasicType::Float128;
  • src/Parser/TypedefTable.cc

    r174845e rbeefc34c  
    1010// Created On       : Sat May 16 15:20:13 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun  1 16:54:18 2018
    13 // Update Count     : 155
     12// Last Modified On : Thu Jun  7 13:17:56 2018
     13// Update Count     : 192
    1414//
    1515
     
    1717#include "TypedefTable.h"
    1818#include <cassert>                                                                              // for assert
     19#include <iostream>
    1920
    2021#if 0
    21 #include <iostream>
    2222#define debugPrint( code ) code
    2323#else
     
    2727using namespace std;                                                                    // string, iostream
    2828
     29debugPrint(
     30static const char *kindName( int kind ) {
     31        switch ( kind ) {
     32          case IDENTIFIER: return "identifier";
     33          case TYPEDEFname: return "typedef";
     34          case TYPEGENname: return "typegen";
     35          default:
     36                cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
     37                abort();
     38        } // switch
     39} // kindName
     40)
     41
    2942TypedefTable::~TypedefTable() {
    3043        if ( ! SemanticErrorThrow && kindTable.currentScope() != 0 ) {
    31                 std::cerr << "scope failure " << kindTable.currentScope() << endl;
     44                cerr << "Error: cfa-cpp internal error, scope failure " << kindTable.currentScope() << endl;
     45                abort();
    3246        } // if
    3347} // TypedefTable::~TypedefTable
     
    4458} // TypedefTable::isKind
    4559
    46 void TypedefTable::changeKind( const string & identifier, int kind ) {
    47         KindTable::iterator posn = kindTable.find( identifier );
    48         if ( posn != kindTable.end() ) posn->second = kind;     // exists => update
    49 } // TypedefTable::changeKind
    50 
    5160// SKULLDUGGERY: Generate a typedef for the aggregate name so the aggregate does not have to be qualified by
    5261// "struct". Only generate the typedef, if the name is not in use. The typedef is implicitly (silently) removed if the
    5362// name is explicitly used.
    54 void TypedefTable::makeTypedef( const string & name ) {
     63void TypedefTable::makeTypedef( const string & name, int kind ) {
     64//    Check for existence is necessary to handle:
     65//        struct Fred {};
     66//        void Fred();
     67//        void fred() {
     68//           struct Fred act; // do not add as type in this scope
     69//           Fred();
     70//        }
    5571        if ( ! typedefTable.exists( name ) ) {
    56                 typedefTable.addToEnclosingScope( name, TYPEDEFname, "MTD" );
     72                typedefTable.addToEnclosingScope( name, kind, "MTD" );
    5773        } // if
    5874} // TypedefTable::makeTypedef
    5975
    60 void TypedefTable::addToScope( const std::string & identifier, int kind, const char * locn __attribute__((unused)) ) {
     76void TypedefTable::addToScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    6177        auto scope = kindTable.currentScope();
    62         debugPrint( cerr << "Adding at " << locn << " " << identifier << " as kind " << kind << " scope " << scope << endl );
     78        debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    6379        auto ret = kindTable.insertAt( scope, identifier, kind );
    6480        if ( ! ret.second ) ret.first->second = kind;           // exists => update
    6581} // TypedefTable::addToScope
    6682
    67 void TypedefTable::addToEnclosingScope( const std::string & identifier, int kind, const char * locn __attribute__((unused)) ) {
     83void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    6884        assert( kindTable.currentScope() >= 1 );
    6985        auto scope = kindTable.currentScope() - 1;
    70         debugPrint( cerr << "Adding+1 at " << locn << " " << identifier << " as kind " << kind << " scope " << scope << endl );
     86        debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    7187        auto ret = kindTable.insertAt( scope, identifier, kind );
    7288        if ( ! ret.second ) ret.first->second = kind;           // exists => update
     
    93109                        debugPrint( cerr << endl << "[" << scope << "]" );
    94110                } // while
    95                 debugPrint( cerr << " " << (*i).first << ":" << (*i).second );
     111                debugPrint( cerr << " " << (*i).first << ":" << kindName( (*i).second ) );
    96112        } // for
    97113        while ( scope > 0 ) {
  • src/Parser/TypedefTable.h

    r174845e rbeefc34c  
    1010// Created On       : Sat May 16 15:24:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 31 23:23:47 2018
    13 // Update Count     : 83
     12// Last Modified On : Thu Jun  7 12:10:17 2018
     13// Update Count     : 85
    1414//
    1515
     
    3030        bool exists( const std::string & identifier );
    3131        int isKind( const std::string & identifier ) const;
    32         void changeKind( const std::string & identifier, int kind );
    33         void makeTypedef( const std::string & name );
     32        void makeTypedef( const std::string & name, int kind = TYPEDEFname );
    3433        void addToScope( const std::string & identifier, int kind, const char * );
    3534        void addToEnclosingScope( const std::string & identifier, int kind, const char * );
  • src/Parser/lex.ll

    r174845e rbeefc34c  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu May  3 13:42:40 2018
    13  * Update Count     : 676
     12 * Last Modified On : Thu Jun  7 08:27:40 2018
     13 * Update Count     : 679
    1414 */
    1515
     
    232232finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    233233float                   { KEYWORD_RETURN(FLOAT); }
     234_Float32                { KEYWORD_RETURN(FLOAT); }                              // GCC
     235_Float32x               { KEYWORD_RETURN(FLOAT); }                              // GCC
     236_Float64                { KEYWORD_RETURN(DOUBLE); }                             // GCC
     237_Float64x               { KEYWORD_RETURN(DOUBLE); }                             // GCC
    234238__float80               { KEYWORD_RETURN(FLOAT80); }                    // GCC
    235239float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
     240_Float128               { KEYWORD_RETURN(FLOAT128); }                   // GCC
     241_Float128x              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    236242__float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    237243float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
     
    446452
    447453%%
     454
    448455// ----end of lexer----
    449456
    450457void yyerror( const char * errmsg ) {
     458        SemanticErrorThrow = true;
    451459        cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    452460                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
  • src/Parser/parser.yy

    r174845e rbeefc34c  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  4 22:22:04 2018
    13 // Update Count     : 3492
     12// Last Modified On : Thu Jun  7 10:07:12 2018
     13// Update Count     : 3527
    1414//
    1515
     
    503503                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    504504        | type_name '.' no_attr_identifier                                      // CFA, nested type
    505                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     505                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     506                { $$ = nullptr; }
    506507        | type_name '.' '[' field_list ']'                                      // CFA, nested type / tuple field selector
    507                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     508                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     509                { $$ = nullptr; }
    508510        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    509511                {
     
    13001302        ;
    13011303
    1302 KR_parameter_list_opt:                                                          // used to declare parameter types in K&R style functions
     1304KR_parameter_list_opt:                                                                  // used to declare parameter types in K&R style functions
    13031305        // empty
    13041306                { $$ = nullptr; }
     
    17901792                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    17911793        | '.' TYPEDEFname
    1792                 { $$ = DeclarationNode::newFromTypedef( $2 ); } // FIX ME
     1794                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17931795        | type_name '.' TYPEDEFname
    1794                 { $$ = DeclarationNode::newFromTypedef( $3 ); } // FIX ME
     1796                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17951797        | typegen_name
    17961798        | '.' typegen_name
    1797                 { $$ = $2; }                                                                    // FIX ME
     1799                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17981800        | type_name '.' typegen_name
    1799                 { $$ = $3; }                                                                    // FIX ME
     1801                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    18001802        ;
    18011803
     
    18221824        aggregate_key attribute_list_opt '{' field_declaration_list_opt '}'
    18231825                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), nullptr, $4, true )->addQualifiers( $2 ); }
    1824         | aggregate_key attribute_list_opt no_attr_identifier_or_type_name
    1825                 {
    1826                         typedefTable.makeTypedef( *$3 );                        // create typedef
    1827                         if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
     1826        | aggregate_key attribute_list_opt no_attr_identifier
     1827                {
     1828                        typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname ); // create typedef
     1829                        //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    18281830                        forall = false;                                                         // reset
    18291831                }
    18301832          '{' field_declaration_list_opt '}'
    18311833                { $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $6, true )->addQualifiers( $2 ); }
     1834        | aggregate_key attribute_list_opt type_name
     1835                {
     1836                        typedefTable.makeTypedef( *$3->type->symbolic.name, forall ? TYPEGENname : TYPEDEFname ); // create typedef
     1837                        //if ( forall ) typedefTable.changeKind( *$3->type->symbolic.name, TYPEGENname ); // possibly update
     1838                        forall = false;                                                         // reset
     1839                }
     1840          '{' field_declaration_list_opt '}'
     1841                { $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, nullptr, $6, true )->addQualifiers( $2 ); }
    18321842        | aggregate_key attribute_list_opt '(' type_list ')' '{' field_declaration_list_opt '}' // CFA
    18331843                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), $4, $7, false )->addQualifiers( $2 ); }
     
    18381848        aggregate_key attribute_list_opt no_attr_identifier
    18391849                {
    1840                         typedefTable.makeTypedef( *$3 );
    1841                         if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
     1850                        typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname );
     1851                        //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    18421852                        forall = false;                                                         // reset
    18431853                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    18441854                }
    1845         | aggregate_key attribute_list_opt TYPEDEFname
    1846                 {
    1847                         typedefTable.makeTypedef( *$3 );
    1848                         $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    1849                 }
    1850         | aggregate_key attribute_list_opt typegen_name         // CFA
     1855        | aggregate_key attribute_list_opt type_name
    18511856                {
    18521857                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
     
    19431948        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    19441949                { $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
    1945         | ENUM attribute_list_opt no_attr_identifier_or_type_name
     1950        | ENUM attribute_list_opt no_attr_identifier
    19461951                { typedefTable.makeTypedef( *$3 ); }
    19471952          '{' enumerator_list comma_opt '}'
    19481953                { $$ = DeclarationNode::newEnum( $3, $6, true )->addQualifiers( $2 ); }
     1954        | ENUM attribute_list_opt type_name
     1955          '{' enumerator_list comma_opt '}'
     1956                { $$ = DeclarationNode::newEnum( $3->type->symbolic.name, $5, true )->addQualifiers( $2 ); }
    19491957        | enum_type_nobody
    19501958        ;
    19511959
    19521960enum_type_nobody:                                                                               // enum - {...}
    1953         ENUM attribute_list_opt no_attr_identifier_or_type_name
     1961        ENUM attribute_list_opt no_attr_identifier
    19541962                {
    19551963                        typedefTable.makeTypedef( *$3 );
    19561964                        $$ = DeclarationNode::newEnum( $3, 0, false )->addQualifiers( $2 );
     1965                }
     1966        | ENUM attribute_list_opt type_name
     1967                {
     1968                        typedefTable.makeTypedef( *$3->type->symbolic.name );
     1969                        $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false )->addQualifiers( $2 );
    19571970                }
    19581971        ;
     
    32513264
    32523265%%
     3266
    32533267// ----end of grammar----
    32543268
  • src/libcfa/bits/locks.h

    r174845e rbeefc34c  
    1818#include "bits/debug.h"
    1919#include "bits/defs.h"
     20#include <assert.h>
     21
     22#ifdef __cforall
     23        extern "C" {
     24                #include <pthread.h>
     25        }
     26#endif
    2027
    2128// pause to prevent excess processor bus usage
     
    112119                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    113120        }
     121
     122
     123        #ifdef __CFA_WITH_VERIFY__
     124                extern bool __cfaabi_dbg_in_kernel();
     125        #endif
     126
     127        struct __bin_sem_t {
     128                bool                    signaled;
     129                pthread_mutex_t         lock;
     130                pthread_cond_t          cond;
     131        };
     132
     133        static inline void ?{}(__bin_sem_t & this) with( this ) {
     134                signaled = false;
     135                pthread_mutex_init(&lock, NULL);
     136                pthread_cond_init (&cond, NULL);
     137        }
     138
     139        static inline void ^?{}(__bin_sem_t & this) with( this ) {
     140                pthread_mutex_destroy(&lock);
     141                pthread_cond_destroy (&cond);
     142        }
     143
     144        static inline void wait(__bin_sem_t & this) with( this ) {
     145                verify(__cfaabi_dbg_in_kernel());
     146                pthread_mutex_lock(&lock);
     147                        if(!signaled) {   // this must be a loop, not if!
     148                                pthread_cond_wait(&cond, &lock);
     149                        }
     150                        signaled = false;
     151                pthread_mutex_unlock(&lock);
     152        }
     153
     154        static inline void post(__bin_sem_t & this) with( this ) {
     155                verify(__cfaabi_dbg_in_kernel());
     156
     157                pthread_mutex_lock(&lock);
     158                        bool needs_signal = !signaled;
     159                        signaled = true;
     160                pthread_mutex_unlock(&lock);
     161
     162                if (needs_signal)
     163                        pthread_cond_signal(&cond);
     164        }
    114165#endif
  • src/libcfa/concurrency/kernel

    r174845e rbeefc34c  
    113113        pthread_t kernel_thread;
    114114
     115        // RunThread data
     116        // Action to do after a thread is ran
     117        struct FinishAction finish;
     118
     119        // Preemption data
     120        // Node which is added in the discrete event simulaiton
     121        struct alarm_node_t * preemption_alarm;
     122
     123        // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
     124        bool pending_preemption;
     125
     126        // Idle lock
     127        __bin_sem_t idleLock;
     128
    115129        // Termination
    116130        // Set to true to notify the processor should terminate
     
    120134        semaphore terminated;
    121135
    122         // RunThread data
    123         // Action to do after a thread is ran
    124         struct FinishAction finish;
    125 
    126         // Preemption data
    127         // Node which is added in the discrete event simulaiton
    128         struct alarm_node_t * preemption_alarm;
    129 
    130         // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
    131         bool pending_preemption;
    132 
    133         // Idle lock
    134         sem_t idleLock;
    135 
    136136        // Link lists fields
    137         struct {
     137        struct __dbg_node_proc {
    138138                struct processor * next;
    139139                struct processor * prev;
     
    182182
    183183        // Link lists fields
    184         struct {
     184        struct __dbg_node_cltr {
    185185                cluster * next;
    186186                cluster * prev;
  • src/libcfa/concurrency/kernel.c

    r174845e rbeefc34c  
    1616//C Includes
    1717#include <stddef.h>
     18#include <errno.h>
     19#include <string.h>
    1820extern "C" {
    1921#include <stdio.h>
     
    4951thread_desc * mainThread;
    5052
    51 struct { __dllist_t(cluster) list; __spinlock_t lock; } global_clusters;
     53extern "C" {
     54struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
     55}
    5256
    5357//-----------------------------------------------------------------------------
     
    143147        runner.proc = &this;
    144148
    145         sem_init(&idleLock, 0, 0);
     149        idleLock{};
    146150
    147151        start( &this );
     
    149153
    150154void ^?{}(processor & this) with( this ){
    151         if( ! do_terminate ) {
     155        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
    152156                __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
    153                 terminate(&this);
    154                 verify(this.do_terminate);
    155                 verify( kernelTLS.this_processor != &this);
     157
     158                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
     159                wake( &this );
     160
    156161                P( terminated );
    157162                verify( kernelTLS.this_processor != &this);
    158                 pthread_join( kernel_thread, NULL );
    159         }
    160 
    161         sem_destroy(&idleLock);
     163        }
     164
     165        pthread_join( kernel_thread, NULL );
    162166}
    163167
     
    198202
    199203                thread_desc * readyThread = NULL;
    200                 for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
     204                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ )
    201205                {
    202206                        readyThread = nextThread( this->cltr );
     
    217221                        else
    218222                        {
    219                                 spin(this, &spin_count);
     223                                // spin(this, &spin_count);
     224                                halt(this);
    220225                        }
    221226                }
     
    290295}
    291296
    292 // Handles spinning logic
    293 // TODO : find some strategy to put cores to sleep after some time
    294 void spin(processor * this, unsigned int * spin_count) {
    295         // (*spin_count)++;
    296         halt(this);
    297 }
    298 
    299297// KERNEL_ONLY
    300298// Context invoker for processors
     
    403401                unlock( ready_queue_lock );
    404402
    405                 if( was_empty ) {
     403                if(was_empty) {
    406404                        lock      (proc_list_lock __cfaabi_dbg_ctx2);
    407405                        if(idles) {
    408                                 wake(idles.head);
     406                                wake_fast(idles.head);
    409407                        }
    410408                        unlock    (proc_list_lock);
    411409                }
     410                else if( struct processor * idle = idles.head ) {
     411                        wake_fast(idle);
     412                }
     413
    412414        }
    413415
     
    544546        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    545547
    546         global_clusters.list{ __get };
    547         global_clusters.lock{};
     548        __cfa_dbg_global_clusters.list{ __get };
     549        __cfa_dbg_global_clusters.lock{};
    548550
    549551        // Initialize the main cluster
     
    626628        // When its coroutine terminates, it return control to the mainThread
    627629        // which is currently here
    628         mainProcessor->do_terminate = true;
     630        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    629631        returnToKernel();
     632        mainThread->self_cor.state = Halted;
    630633
    631634        // THE SYSTEM IS NOW COMPLETELY STOPPED
     
    643646        ^(mainThread){};
    644647
    645         ^(global_clusters.list){};
    646         ^(global_clusters.lock){};
     648        ^(__cfa_dbg_global_clusters.list){};
     649        ^(__cfa_dbg_global_clusters.lock){};
    647650
    648651        __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n");
     
    654657
    655658void halt(processor * this) with( *this ) {
     659        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
     660
    656661        with( *cltr ) {
    657662                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     
    663668        __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
    664669
    665         verify( ({int sval = 0; sem_getvalue(&this->idleLock, &sval); sval; }) < 200);
    666         int __attribute__((unused)) ret = sem_wait(&idleLock);
    667         verify(ret > 0 || errno == EINTR);
     670        wait( idleLock );
    668671
    669672        __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
     
    675678                unlock    (proc_list_lock);
    676679        }
    677 }
    678 
    679 void wake(processor * this) {
    680         __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
    681         int __attribute__((unused)) ret = sem_post(&this->idleLock);
    682         verify(ret > 0 || errno == EINTR);
    683         verify( ({int sval = 0; sem_getvalue(&this->idleLock, &sval); sval; }) < 200);
    684680}
    685681
     
    797793// Global Queues
    798794void doregister( cluster     & cltr ) {
    799         lock      ( global_clusters.lock __cfaabi_dbg_ctx2);
    800         push_front( global_clusters.list, cltr );
    801         unlock    ( global_clusters.lock );
     795        lock      ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
     796        push_front( __cfa_dbg_global_clusters.list, cltr );
     797        unlock    ( __cfa_dbg_global_clusters.lock );
    802798}
    803799
    804800void unregister( cluster     & cltr ) {
    805         lock  ( global_clusters.lock __cfaabi_dbg_ctx2);
    806         remove( global_clusters.list, cltr );
    807         unlock( global_clusters.lock );
     801        lock  ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
     802        remove( __cfa_dbg_global_clusters.list, cltr );
     803        unlock( __cfa_dbg_global_clusters.lock );
    808804}
    809805
  • src/libcfa/concurrency/kernel_private.h

    r174845e rbeefc34c  
    5858void finishRunning(processor * this);
    5959void halt(processor * this);
    60 void wake(processor * this);
    61 void terminate(processor * this);
    62 void spin(processor * this, unsigned int * spin_count);
     60
     61static inline void wake_fast(processor * this) {
     62        __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
     63        post( this->idleLock );
     64}
     65
     66static inline void wake(processor * this) {
     67        disable_interrupts();
     68        wake_fast(this);
     69        enable_interrupts( __cfaabi_dbg_ctx );
     70}
    6371
    6472struct event_kernel_t {
     
    6876
    6977extern event_kernel_t * event_kernel;
    70 
    71 //extern thread_local coroutine_desc * volatile this_coroutine;
    72 //extern thread_local thread_desc *    volatile this_thread;
    73 //extern thread_local processor *      volatile this_processor;
    74 
    75 // extern volatile thread_local bool preemption_in_progress;
    76 // extern volatile thread_local bool preemption_enabled;
    77 // extern volatile thread_local unsigned short disable_preempt_count;
    7878
    7979struct __cfa_kernel_preemption_state_t {
  • src/libcfa/concurrency/preemption.c

    r174845e rbeefc34c  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr  9 13:52:39 2018
    13 // Update Count     : 36
     12// Last Modified On : Tue Jun  5 17:35:49 2018
     13// Update Count     : 37
    1414//
    1515
     
    116116        // If there are still alarms pending, reset the timer
    117117        if( alarms->head ) {
    118                 __cfaabi_dbg_print_buffer_decl( " KERNEL: @%lu(%lu) resetting alarm to %lu.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
     118                __cfaabi_dbg_print_buffer_decl( " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
    119119                Duration delta = alarms->head->alarm - currtime;
    120120                Duration caped = max(delta, 50`us);
     
    263263}
    264264
    265 // kill wrapper : signal a processor
    266 void terminate(processor * this) {
    267         this->do_terminate = true;
    268         wake(this);
    269         sigval_t value = { PREEMPT_TERMINATE };
    270         pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    271 }
    272 
    273265// reserved for future use
    274266static void timeout( thread_desc * this ) {
     
    369361        choose(sfp->si_value.sival_int) {
    370362                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
    371                 case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate);
     363                case PREEMPT_TERMINATE: verify( __atomic_load_n( &kernelTLS.this_processor->do_terminate, __ATOMIC_SEQ_CST ) );
    372364                default:
    373365                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     
    488480}
    489481
     482#ifdef __CFA_WITH_VERIFY__
     483bool __cfaabi_dbg_in_kernel() {
     484        return !kernelTLS.preemption_state.enabled;
     485}
     486#endif
     487
    490488// Local Variables: //
    491489// mode: c //
  • src/libcfa/fstream

    r174845e rbeefc34c  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec  7 15:17:26 2017
    13 // Update Count     : 130
     12// Last Modified On : Tue Jun  5 10:20:25 2018
     13// Update Count     : 131
    1414//
    1515
     
    5454void open( ofstream &, const char * name );
    5555void close( ofstream & );
    56 ofstream & write( ofstream &, const char * data, unsigned long int size );
     56ofstream & write( ofstream &, const char * data, size_t size );
    5757int fmt( ofstream &, const char fmt[], ... );
    5858
     
    7474void open( ifstream & is, const char * name );
    7575void close( ifstream & is );
    76 ifstream & read( ifstream & is, char * data, unsigned long int size );
     76ifstream & read( ifstream & is, char * data, size_t size );
    7777ifstream & ungetc( ifstream & is, char c );
    7878int fmt( ifstream &, const char fmt[], ... );
  • src/libcfa/fstream.c

    r174845e rbeefc34c  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Dec  9 09:31:23 2017
    13 // Update Count     : 275
     12// Last Modified On : Tue Jun  5 17:02:56 2018
     13// Update Count     : 281
    1414//
    1515
     
    116116} // close
    117117
    118 ofstream & write( ofstream & os, const char * data, unsigned long int size ) {
     118ofstream & write( ofstream & os, const char * data, size_t size ) {
    119119        if ( fail( os ) ) {
    120120                fprintf( stderr, "attempt write I/O on failed stream\n" );
     
    198198} // close
    199199
    200 ifstream & read( ifstream & is, char * data, unsigned long int size ) {
     200ifstream & read( ifstream & is, char * data, size_t size ) {
    201201        if ( fail( is ) ) {
    202202                fprintf( stderr, "attempt read I/O on failed stream\n" );
  • src/libcfa/stdhdr/assert.h

    r174845e rbeefc34c  
    3333        #define verify(x) assert(x)
    3434        #define verifyf(x, ...) assertf(x, __VA_ARGS__)
     35        #define __CFA_WITH_VERIFY__
    3536#else
    3637        #define verify(x)
  • src/main.cc

    r174845e rbeefc34c  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 30 17:53:14 2018
    13 // Update Count     : 496
     12// Last Modified On : Wed Jun  6 15:51:47 2018
     13// Update Count     : 498
    1414//
    1515
     
    157157                 << "." << endl;
    158158        backtrace( 2 );                                                                         // skip first 2 stack frames
    159         exit( EXIT_FAILURE );
     159        //_exit( EXIT_FAILURE );
     160        abort();
    160161} // sigSegvBusHandler
    161162
  • src/prelude/extras.regx

    r174845e rbeefc34c  
    11typedef.* size_t;
    22typedef.* ptrdiff_t;
     3typedef.* __int8_t;
     4typedef.* __int16_t;
     5typedef.* __int32_t;
     6typedef.* __int64_t;
     7typedef.* __uint8_t;
     8typedef.* __uint16_t;
     9typedef.* __uint32_t;
     10typedef.* __uint64_t;
    311typedef.* int8_t;
    412typedef.* int16_t;
  • src/prelude/sync-builtins.cf

    r174845e rbeefc34c  
    248248#endif
    249249
     250_Bool __atomic_load_n(const volatile _Bool *, int);
     251void __atomic_load(const volatile _Bool *, volatile _Bool *, int);
    250252char __atomic_load_n(const volatile char *, int);
    251253char __atomic_load_1(const volatile char *, int);
     
    285287
    286288void __atomic_store_n(volatile _Bool *, _Bool, int);
    287 void __atomic_store_1(volatile _Bool *, _Bool, int);
    288289void __atomic_store(volatile _Bool *, _Bool *, int);
    289290void __atomic_store_n(volatile char *, char, int);
  • src/tests/Makefile.am

    r174845e rbeefc34c  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Nov 27 21:34:33 2017
    14 ## Update Count     : 48
     13## Last Modified On : Wed Jun  6 16:42:20 2018
     14## Update Count     : 49
    1515###############################################################################
    1616
     
    9292        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    9393
    94 literals : literals.c @CFA_BINDIR@/@CFA_NAME@
    95         ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    96 
    9794sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@
    9895        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/Makefile.in

    r174845e rbeefc34c  
    769769        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    770770
    771 literals : literals.c @CFA_BINDIR@/@CFA_NAME@
    772         ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    773 
    774771sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@
    775772        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/ifwhileCtl.c

    r174845e rbeefc34c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ifcond.c --
     7// ifwhileCtl.c --
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Aug 26 10:13:11 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  4 22:46:48 2018
    13 // Update Count     : 19
     12// Last Modified On : Wed Jun  6 17:15:09 2018
     13// Update Count     : 21
    1414//
    1515
     
    7272// Local Variables: //
    7373// tab-width: 4 //
    74 // compile-command: "cfa ifcond.c" //
     74// compile-command: "cfa ifwhileCtl.c" //
    7575// End: //
  • src/tests/preempt_longrun/enter.c

    r174845e rbeefc34c  
    1515
    1616monitor mon_t {};
     17void foo( mon_t & mutex this ) {}
    1718
    1819mon_t mon;
    19 
    20 void foo( mon_t & mutex this ) {}
    21 
    2220thread worker_t {};
    23 
    2421void main( worker_t & this ) {
    2522        for( unsigned long i = 0; i < N; i++ ) {
     
    2825}
    2926
    30 extern "C" {
    31 static worker_t * workers;
    32 }
    33 
    3427int main(int argc, char * argv[] ) {
    3528        processor p;
    3629        {
    3730                worker_t w[7];
    38                 workers = w;
    3931        }
    4032}
  • src/tests/preempt_longrun/processor.c

    r174845e rbeefc34c  
    22#include <thread>
    33#include <time>
     4
     5#include <unistd.h>
    46
    57#ifndef PREEMPTION_RATE
     
    1113}
    1214
    13 static const unsigned long N = 5_000ul;
     15static const unsigned long N = 50_000ul;
    1416
    1517int main(int argc, char* argv[]) {
    1618        processor * p[15];
     19        write(STDOUT_FILENO, "Preparing\n", sizeof("Preparing\n"));
    1720        for ( int pi = 0; pi < 15; pi++ ) {
    1821                p[pi] = new();
    1922        }
     23        write(STDOUT_FILENO, "Starting\n", sizeof("Starting\n"));
    2024        for ( int i = 0; i < N; i++) {
    2125                int pi = i % 15;
     
    2327                p[pi] = new();
    2428        }
     29        write(STDOUT_FILENO, "Stopping\n", sizeof("Stopping\n"));
    2530        for ( int pi = 0; pi < 15; pi++ ) {
    2631                delete( p[pi] );
    2732        }
     33        write(STDOUT_FILENO, "Done\n", sizeof("Done\n"));
    2834}
Note: See TracChangeset for help on using the changeset viewer.