Changes in / [7d0a3ba:358cba0]
- Files:
-
- 14 added
- 15 deleted
- 36 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
r7d0a3ba r358cba0 260 260 def install_dir = pwd tmp: true 261 261 262 //Output compiler version to help with debug 263 echo """C++ Compiler :""" 264 sh "which ${compiler.cpp_cc} && ${compiler.cpp_cc} --version" 265 echo """C Compiler :""" 266 sh "which ${compiler.cfa_cc} && ${compiler.cfa_cc} --version" 267 262 268 //Configure the conpilation (Output is not relevant) 263 //Use the current directory as the installation target so nothing 264 //escapes the sandbox 269 //Use the current directory as the installation target so nothing escapes the sandbox 265 270 //Also specify the compiler by hand 266 271 sh "./configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet" -
doc/bibliography/pl.bib
r7d0a3ba r358cba0 782 782 howpublished= {\href{http://www.boost.org/doc/libs/1_61_0/libs/coroutine/doc/html/index.html} 783 783 {{http://www.boost.org/\-doc/\-libs/1\_61\_0/\-libs/\-coroutine/\-doc/\-html/\-index.html}}}, 784 note = {Accessed: 2016-09},784 optnote = {Accessed: 2016-09}, 785 785 } 786 786 … … 855 855 keywords = {ANSI C 89}, 856 856 contributer = {gjditchfield@plg}, 857 title = {American National Standard for Information Systems -- Programming Language -- {C}}, 857 author = {C90}, 858 title = {Programming Languages -- {C}}, 858 859 organization= {American National Standards Institute}, 859 address = {1430 Broadway, New York, New York 10018}, 860 month = dec, 861 year = 1989, 862 note = {X3.159-1989} 860 address = {New York, NY, U.S.A.}, 861 year = 1990, 862 note = {ANSI/ISO 9899-1990} 863 863 } 864 864 … … 888 888 title = {\textsf{C}{$\mathbf{\forall}$} Features}, 889 889 howpublished= {\url{https://plg.uwaterloo.ca/~cforall/features}}, 890 note = {Accessed: 2018-01-01},890 optnote = {Accessed: 2018-01-01}, 891 891 } 892 892 … … 900 900 address = {Waterloo, Ontario, Canada, N2L 3G1}, 901 901 note = {\href{http://plg.uwaterloo.ca/theses/EstevesThesis.pdf}{http://\-plg.uwaterloo.ca/\-theses/\-EstevesThesis.pdf}}, 902 } 903 904 @misc{CFAStackEvaluation, 905 author = {Aaron Moss}, 906 title = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs}, 907 year = 2018, 908 howpublished= {\href{https://plg.uwaterloo.ca/~cforall/evaluation.zip}{https://plg.uwaterloo.ca/\-\-$\sim$cforall/\-StackEvaluation.zip}}, 909 optnote = {[Accessed May 2018]}, 902 910 } 903 911 … … 1640 1648 } 1641 1649 1650 @misc{Taylor10, 1651 keywords = {const, poisoning}, 1652 contributer = {pabuhr@plg}, 1653 author = {Ian Lance Taylor}, 1654 title = {const}, 1655 month = oct, 1656 year = 2010, 1657 howpublished= {\href{https://www.airs.com/blog/archives/428} 1658 {https://www.airs.com/\-blog/\-archives/\-428}}, 1659 optnote = {Accessed: 2018-05}, 1660 } 1661 1642 1662 @phdthesis{Ditchfield92, 1643 1663 keywords = {C, parametric polymorphism, overloading}, … … 2755 2775 @misc{GCCExtensions, 2756 2776 contributer = {a3moss@uwaterloo.ca}, 2757 key = { {GNU}},2777 key = {C Extensions}, 2758 2778 author = {{C Extensions}}, 2759 2779 title = {Extensions to the {C} Language Family}, 2760 2780 year = 2014, 2761 2781 howpublished= {\href{https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/C-Extensions.html}{https://\-gcc.gnu.org/\-onlinedocs/\-gcc-4.7.2/\-gcc/\-C\-Extensions.html}}, 2762 note = {Accessed: 2017-04-02},2782 optnote = {Accessed: 2017-04-02}, 2763 2783 } 2764 2784 … … 2947 2967 month = jul, year = 1987, 2948 2968 volume = 4, number = 4, pages = {9-16} 2969 } 2970 2971 @misc{Sutter05c, 2972 contributer = {pabuhr@plg}, 2973 title = {The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software}, 2974 author = {Herb Sutter}, 2975 howpublished= {\url{http://www.gotw.ca/publications/concurrency-ddj.htm}}, 2976 year = {2005}, 2977 note = {originally Dr. Dobb's Journal 30(3)}, 2949 2978 } 2950 2979 … … 3137 3166 year = 2014, 3138 3167 howpublished= {https://developer.gnome.org/gobject/stable/}, 3139 note = {Accessed: 2017-04},3168 optnote = {Accessed: 2017-04}, 3140 3169 } 3141 3170 … … 3209 3238 3210 3239 % H 3240 3241 @manual{Haskell10, 3242 keywords = {Haskell}, 3243 contributer = {pabuhr@plg}, 3244 author = {Haskell}, 3245 title = {Haskell 2010 Language Report}, 3246 edition = {{S}imon {M}arlow}, 3247 year = 2010, 3248 note = {\href{https://haskell.org/definition/haskell2010.pdf}{https://haskell.org/\-definition/\-haskell2010.pdf}}, 3249 } 3211 3250 3212 3251 @article{Michael04a, … … 3760 3799 keywords = {concurrency, critical section}, 3761 3800 contributer = {pabuhr@plg}, 3762 author = {Dominic Duggan and G ordonV. Cormack and John Ophel},3801 author = {Dominic Duggan and G. V. Cormack and John Ophel}, 3763 3802 title = {Kinded Type Inference for Parametric Overloading}, 3764 3803 journal = acta, … … 4685 4724 year = 2015, 4686 4725 howpublished= {\href{https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectiveC.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-General/\-Conceptual/\-DevPedia-\-CocoaCore/\-ObjectiveC.html}}, 4687 note = {Accessed: 2018-03}4726 optnote = {Accessed: 2018-03} 4688 4727 } 4689 4728 … … 4695 4734 year = 2015, 4696 4735 howpublished= {\href{https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc7_release_notes.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-Xcode/\-Conceptual/\-RN-Xcode-Archive/\-Chapters/\-xc7\_release\_notes.html}}, 4697 note = {Accessed: 2017-04}4736 optnote = {Accessed: 2017-04} 4698 4737 } 4699 4738 … … 5757 5796 keywords = {Cyclone, existential types, polymorphism, type variables}, 5758 5797 contributer = {a3moss@plg}, 5759 author = {D anGrossman},5798 author = {D. Grossman}, 5760 5799 title = {Quantified Types in an Imperative Language}, 5761 5800 journal = toplas, … … 6762 6801 title = {{TIOBE} Index}, 6763 6802 howpublished= {\href{http://www.tiobe.com/tiobe_index}{http://\-www.tiobe.com/\-tiobe\_index}}, 6764 note = {Accessed: 2018-09},6803 optnote = {Accessed: 2018-09}, 6765 6804 } 6766 6805 … … 7087 7126 year = 2017, 7088 7127 howpublished= {\url{https://wiki.gnome.org/Projects/Vala/Manual}}, 7089 note = {Accessed: 2017-04}7128 optnote = {Accessed: 2017-04} 7090 7129 } 7091 7130 -
doc/papers/AMA/AMA-stix/Documents/README.txt
r7d0a3ba r358cba0 13 13 % NJDnatbib.sty --> NJD natbib reference package. 14 14 % Stix-Fonts (folder) --> Stix font files 15 16 % MiKTeX 2.9 (Freeware software) is required to install STIX/LATO fonts 17 % Download MiKTeX installer & instructions from the below URLs 18 https://miktex.org/download 19 Instructions to install the basic MiKTeX installer 20 https://miktex.org/howto/install-miktex 21 22 % Execute(double click) --> Windows-Stix-fontinstaller.exe from Stix-Fonts folder (This EXE file will install fonts to local drive) (please rename Windows-Stix-fontinstaller.e_xe to Windows-Stix-fontinstaller.exe) 15 % Execute(double click) --> Windows-Stix-fontinstaller.exe from Stix-Fonts folder (This EXE file will install fonts to local drive) 23 16 % Still shows font error, please do the following 24 17 % Start-->run--> type "mo_edmin.exe" and press enter -
doc/papers/AMA/AMA-stix/ama/WileyNJD-AMA.bst
r7d0a3ba r358cba0 502 502 editor empty$ 503 503 { booktitle emphasize * } 504 504 { " " * format.editors * " " * booktitle emphasize * ", " * } 505 505 if$ 506 506 } … … 691 691 { format.journal emphasize "journal" output.check 692 692 format.date add.semicolon "year" output.check 693 blank.sep 693 694 format.volume output 694 695 format.number output … … 824 825 new.block 825 826 format.pages output 827 new.block 826 828 organization output 829 new.block 827 830 publisher output 828 831 inproformat.date "year" output.check … … 863 866 { new.block organization new.block address new.block.checkb 864 867 organization output 868 new.block 865 869 address output 866 870 } … … 883 887 new.block 884 888 school "school" output.check 889 new.block 885 890 address output 886 891 format.date "year" output.check … … 927 932 "PhD thesis" format.thesis.type output.nonnull 928 933 school "school" output.check 934 new.block 929 935 address output 930 936 format.date "year" output.check -
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls
r7d0a3ba r358cba0 484 484 \if@STIXLargeOneCol% 485 485 \RequirePackage[not1,notextcomp,lcgreekalpha]{stix}% 486 %\usepackage[scaled]{helvet}487 %\renewcommand\familydefault{\sfdefault}488 486 \usepackage[T1]{fontenc} 489 487 \BXhsize=170mm% … … 528 526 %\RequirePackage[not1,notextcomp,lcgreekalpha]{stix}% 529 527 530 \captionsetup[figure]{labelformat=simple, labelsep= space, skip=10pt, labelfont=bf}531 \captionsetup[table]{labelformat=simple, labelsep= space, skip=10pt, labelfont=bf}532 \renewcommand{\thefigure}{\arabic{figure} }533 534 \renewcommand{\thetable}{\arabic{table} }528 \captionsetup[figure]{labelformat=simple, labelsep=none, skip=10pt, labelfont=bf} 529 \captionsetup[table]{labelformat=simple, labelsep=none, skip=10pt, labelfont=bf} 530 \renewcommand{\thefigure}{\arabic{figure}\enspace } 531 532 \renewcommand{\thetable}{\arabic{table}\enspace } 535 533 536 534 \renewcommand\figurename{\textbf{FIGURE}}%% … … 1414 1412 \gdef\@stix@font@defn{% 1415 1413 % 1416 %\def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%1414 \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}% 1417 1415 % 1418 %\def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}1416 \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont} 1419 1417 % 1420 1418 \def\pagenumfont{\rmfamily\fontsize{7}{9}\bfseries\selectfont}% … … 1429 1427 \def\arttypefont{\rmfamily\fontsize{9}{9}\fontseries{b}\selectfont}% 1430 1428 \def\SParttypefont{\rmfamily\fontsize{9}{12}\fontseries{b}\selectfont}% 1431 \def\titlefont{\rmfamily\fontsize{18}{23}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil }%1429 \def\titlefont{\rmfamily\fontsize{18}{23}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil\let\mathbcal\titmathbcal}% 1432 1430 \def\subtitlefont{\rmfamily\fontsize{16}{21}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil}% 1433 1431 \def\Authorfont{\rmfamily\fontsize{12}{18}\selectfont\leftskip\z@\rightskip\z@ plus1fil}% … … 1484 1482 \gdef\@lato@font@defn{% 1485 1483 % 1486 %\def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%1484 \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}% 1487 1485 % 1488 %\def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}1486 \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont} 1489 1487 % 1490 1488 \def\pagenumfont{\rmfamily\fontsize{7}{9}\bfseries\selectfont}% … … 3249 3247 \fi 3250 3248 \fi% 3251 \renewcommand\thefigure{\@Alph\c@section\arabic{figure} }%3252 \renewcommand\thetable{\@Alph\c@section\arabic{table} }%3249 \renewcommand\thefigure{\@Alph\c@section\arabic{figure}\enspace }% 3250 \renewcommand\thetable{\@Alph\c@section\arabic{table}\enspace }% 3253 3251 \renewcommand\theequation{\@Alph\c@section\arabic{equation}}% 3254 3252 }{% -
doc/papers/general/.gitignore
r7d0a3ba r358cba0 8 8 Paper.out.ps 9 9 WileyNJD-AMA.bst 10 evaluation.zip -
doc/papers/general/Makefile
r7d0a3ba r358cba0 45 45 @rm -frv ${DOCUMENT} ${BASE}.ps WileyNJD-AMA.bst ${BASE}.out.ps ${Build} 46 46 47 Paper.zip : 48 zip -x general/.gitignore -x general/"*AMA*" -x general/Paper.out.ps -x general/Paper.tex.plain -x general/evaluation.zip -x general/mail -x general/response -x general/test.c -x general/evaluation.zip -x general/Paper.tex.plain -x general/Paper.ps -x general/Paper.pdf -x general/"*build*" -x general/evaluation/.gitignore -x general/evaluation/timing.xlsx -r Paper.zip general 49 50 evaluation.zip : 51 zip -x evaluation/.gitignore -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation 52 47 53 # File Dependencies # 48 54 … … 66 72 ## Define the default recipes. 67 73 68 ${Build} :74 ${Build} : 69 75 mkdir -p ${Build} 70 76 71 ${BASE}.out.ps : ${Build}77 ${BASE}.out.ps : ${Build} 72 78 ln -fs ${Build}/Paper.out.ps . 73 79 74 WileyNJD-AMA.bst :80 WileyNJD-AMA.bst : 75 81 ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst . 76 82 -
doc/papers/general/Paper.tex
r7d0a3ba r358cba0 59 59 %\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}} 60 60 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 61 62 \renewcommand*{\thefootnote}{\Alph{footnote}} % hack because fnsymbol does not work 63 %\renewcommand*{\thefootnote}{\fnsymbol{footnote}} 61 64 62 65 \makeatletter … … 174 177 \lstMakeShortInline@% 175 178 179 \let\OLDthebibliography\thebibliography 180 \renewcommand\thebibliography[1]{ 181 \OLDthebibliography{#1} 182 \setlength{\parskip}{0pt} 183 \setlength{\itemsep}{4pt plus 0.3ex} 184 } 176 185 177 186 \title{\texorpdfstring{\protect\CFA : Adding Modern Programming Language Features to C}{Cforall : Adding Modern Programming Language Features to C}} … … 191 200 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects. 192 201 This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more. 193 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive. 194 The goal of the \CFA project is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers. 202 Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive. 203 204 The goal of the \CFA project (pronounced ``C-for-all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers. 195 205 Prior projects have attempted similar goals but failed to honour C programming-style; for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers. 196 206 Specifically, \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code-bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers. … … 226 236 Love it or hate it, C is extremely popular, highly used, and one of the few systems languages. 227 237 In many cases, \CC is often used solely as a better C. 228 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive.238 Nevertheless, C, first standardized almost forty years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive. 229 239 230 240 \CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining both source and runtime compatibility with C and a familiar programming model for programmers. … … 239 249 All languages features discussed in this paper are working, except some advanced exception-handling features. 240 250 Not discussed in this paper are the integrated concurrency-constructs and user-level threading-library~\cite{Delisle18}. 241 \CFA is an \emph{open-source} project implemented as a nsource-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3).251 \CFA is an \emph{open-source} project implemented as a source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3). 242 252 Ultimately, a compiler is necessary for advanced features and optimal performance. 243 253 % @plg2[9]% cd cfa-cc/src; cloc ArgTweak CodeGen CodeTools Common Concurrency ControlStruct Designators GenPoly InitTweak MakeLibCfa.cc MakeLibCfa.h Parser ResolvExpr SymTab SynTree Tuples driver prelude main.cc … … 292 302 The \CFA tests are 290+ files and 27,000+ lines of code. 293 303 The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks. 294 The tests check for correctness and are used for daily regression testing of commits (3800+).304 The tests check for correctness and are used for daily regression testing of 3800+ commits. 295 305 296 306 Finally, it is impossible to describe a programming language without usages before definitions. … … 313 323 There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton 314 324 \end{quote} 315 \vspace{- 10pt}325 \vspace{-9pt} 316 326 C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax. 317 327 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; … … 324 334 int max( int a, int b ) { return a < b ? b : a; } $\C{// (3)}$ 325 335 double max( double a, double b ) { return a < b ? b : a; } $\C{// (4)}\CRT$ 326 max( 7, -max ); $\C [2.75in]{// uses (3) and (1), by matching int from constant 7}$336 max( 7, -max ); $\C{// uses (3) and (1), by matching int from constant 7}$ 327 337 max( max, 3.14 ); $\C{// uses (4) and (2), by matching double from constant 3.14}$ 328 max( max, -max ); $\C{// ERROR :ambiguous}$329 int m = max( max, -max ); $\C{// uses (3) and (1) twice, by matching return type} \CRT$338 max( max, -max ); $\C{// ERROR, ambiguous}$ 339 int m = max( max, -max ); $\C{// uses (3) and (1) twice, by matching return type}$ 330 340 \end{cfa} 331 341 … … 336 346 As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities. 337 347 338 \Celeven added @_Generic@ expressions , which is used in preprocessor macros to provide a form ofad-hoc polymorphism;348 \Celeven added @_Generic@ expressions~\cite[\S~6.5.1.1]{C11}, which is used with preprocessor macros to provide ad-hoc polymorphism; 339 349 however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 340 350 The macro wrapping the generic expression imposes some limitations; 341 351 \eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@. 342 352 Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the dispatch functions, which must all have distinct names. 343 For backwards compatibility, \CFA supports @_Generic@ expressions, but it is an unnecessary mechanism. \TODO{actually implement that}353 \CFA supports @_Generic@ expressions for backwards compatibility, but it is an unnecessary mechanism. \TODO{actually implement that} 344 354 345 355 % http://fanf.livejournal.com/144696.html … … 369 379 \begin{cfa} 370 380 forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; } $\C{// ? denotes operands}$ 371 int val = twice( twice( 3.7 ) ); 381 int val = twice( twice( 3.7 ) ); $\C{// val == 14}$ 372 382 \end{cfa} 373 383 which works for any type @T@ with a matching addition operator. 374 384 The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@. 375 385 There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis. 376 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an ea gerconversion to @int@.386 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an early conversion to @int@. 377 387 \CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition. 378 388 … … 420 430 \begin{cfa} 421 431 forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ } 422 {432 int main() { 423 433 int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$ 424 qsort( vals, size );$\C{// descending sort}$434 qsort( vals, 10 ); $\C{// descending sort}$ 425 435 } 426 436 \end{cfa} … … 428 438 Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types. 429 439 430 To reduc ingduplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}).440 To reduce duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}). 431 441 \begin{cfa} 432 442 forall( otype `T` ) { $\C{// distribution block, add forall qualifier to declarations}$ … … 470 480 \end{cquote} 471 481 472 In fact, the set of @summable@ trait operators is incomplete, as it is missing assignment for type @T@, but @otype@ is syntactic sugar for the following implicit trait: 482 Note, the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return; 483 it is provided by @otype@, which is syntactic sugar for the following trait: 473 484 \begin{cfa} 474 485 trait otype( dtype T | sized(T) ) { // sized is a pseudo-trait for types with known size and alignment … … 488 499 Instead, each polymorphic function (or generic type) defines the structural type needed for its execution (polymorphic type-key), and this key is fulfilled at each call site from the lexical environment, which is similar to Go~\cite{Go} interfaces. 489 500 Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal-inheritance hierarchy. 490 (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)501 % (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.) 491 502 492 503 % Nominal inheritance can be simulated with traits using marker variables or functions: … … 515 526 516 527 517 \vspace*{-2pt}518 528 \section{Generic Types} 519 529 … … 534 544 \begin{cquote} 535 545 \lstDeleteShortInline@% 536 \begin{tabular}{@{}l|@{\hspace{ 2\parindentlnth}}l@{}}537 \begin{cfa} 538 forall( otype R, otype S )struct pair {546 \begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}} 547 \begin{cfa} 548 `forall( otype R, otype S )` struct pair { 539 549 R first; S second; 540 550 }; … … 561 571 Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters. 562 572 A \newterm{dtype-static} type has polymorphic parameters but is still concrete. 563 Polymorphic pointers are an example of dtype-static types, \eg @forall(dtype T) T *@ is a polymorphic type, but for any @T@, @T *@ is a fixed-sized pointer, and therefore, can be represented by a @void *@ in code generation. 573 Polymorphic pointers are an example of dtype-static types; 574 given some type variable @T@, @T@ is a polymorphic type, as is @T *@, but @T *@ has a fixed size and can therefore be represented by @void *@ in code generation. 564 575 565 576 \CFA generic types also allow checked argument-constraints. … … 578 589 \begin{cfa} 579 590 struct _pair_conc0 { 580 const char * first; 581 int second; 591 const char * first; int second; 582 592 }; 583 593 \end{cfa} … … 587 597 \begin{cfa} 588 598 struct _pair_conc1 { 589 void * first; 590 void * second; 599 void * first, * second; 591 600 }; 592 601 \end{cfa} … … 645 654 \begin{cquote} 646 655 \lstDeleteShortInline@% 647 \begin{tabular}{@{}l @{\hspace{2\parindentlnth}}l@{}}656 \begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}} 648 657 \begin{cfa} 649 658 forall( dtype Unit ) struct scalar { unsigned long value; }; … … 661 670 half_marathon; 662 671 scalar(litres) two_pools = pool + pool; 663 `marathon + pool;` // compilation ERROR672 `marathon + pool;` // ERROR, mismatched types 664 673 \end{cfa} 665 674 \end{tabular} … … 947 956 } 948 957 \end{cfa} 949 One more step permits the summation of any sum mable type with all arguments of the same type:950 \begin{cfa} 951 trait sum mable( otype T ) {958 One more step permits the summation of any sumable type with all arguments of the same type: 959 \begin{cfa} 960 trait sumable( otype T ) { 952 961 T ?+?( T, T ); 953 962 }; 954 forall( otype R | sum mable( R ) ) R sum( R x, R y ) {963 forall( otype R | sumable( R ) ) R sum( R x, R y ) { 955 964 return x + y; 956 965 } 957 forall( otype R, ttype Params | sum mable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) {966 forall( otype R, ttype Params | sumable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) { 958 967 return sum( x + y, rest ); 959 968 } … … 1006 1015 \begin{cfa} 1007 1016 forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 { 1008 T0 field_0; $\C{// generated before the first 2-tuple}$ 1009 T1 field_1; 1017 T0 field_0; T1 field_1; $\C{// generated before the first 2-tuple}$ 1010 1018 }; 1011 1019 _tuple2(int, int) f() { 1012 1020 _tuple2(double, double) x; 1013 1021 forall( dtype T0, dtype T1, dtype T2 | sized(T0) | sized(T1) | sized(T2) ) struct _tuple3 { 1014 T0 field_0; $\C{// generated before the first 3-tuple}$ 1015 T1 field_1; 1016 T2 field_2; 1022 T0 field_0; T1 field_1; T2 field_2; $\C{// generated before the first 3-tuple}$ 1017 1023 }; 1018 1024 _tuple3(int, double, int) y; 1019 1025 } 1020 1026 \end{cfa} 1021 {\sloppy 1022 Tuple expressions are then simply converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char, double)){ 5, 'x', 1.24 }@. 1023 \par}% 1027 Tuple expressions are then converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char,@ @double)){ 5, 'x', 1.24 }@. 1024 1028 1025 1029 \begin{comment} … … 1106 1110 \lstDeleteShortInline@% 1107 1111 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1108 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1112 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1109 1113 \begin{cfa} 1110 1114 case 2, 10, 34, 42: … … 1121 1125 \lstDeleteShortInline@% 1122 1126 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1123 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1127 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1124 1128 \begin{cfa} 1125 1129 case 2~42: … … 1174 1178 \centering 1175 1179 \lstDeleteShortInline@% 1176 \begin{tabular}{@{}l @{\hspace{2\parindentlnth}}l@{}}1177 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1180 \begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}} 1181 \multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1178 1182 \begin{cfa} 1179 1183 `choose` ( day ) { 1180 1184 case Mon~Thu: // program 1181 1185 1182 case Fri: // program1186 case Fri: // program 1183 1187 wallet += pay; 1184 1188 `fallthrough;` 1185 case Sat: // party1189 case Sat: // party 1186 1190 wallet -= party; 1187 1191 1188 1192 case Sun: // rest 1189 1193 1190 default: //error1194 default: // print error 1191 1195 } 1192 1196 \end{cfa} … … 1196 1200 case Mon: case Tue: case Wed: case Thu: // program 1197 1201 `break;` 1198 case Fri: // program1202 case Fri: // program 1199 1203 wallet += pay; 1200 1204 1201 case Sat: // party1205 case Sat: // party 1202 1206 wallet -= party; 1203 1207 `break;` 1204 1208 case Sun: // rest 1205 1209 `break;` 1206 default: //error1210 default: // print error 1207 1211 } 1208 1212 \end{cfa} … … 1220 1224 \centering 1221 1225 \lstDeleteShortInline@% 1222 \begin{tabular}{@{}l @{\hspace{2\parindentlnth}}l@{}}1223 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{non-terminator}} & \multicolumn{1}{c}{\textbf{target label}} \\1226 \begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}} 1227 \multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{non-terminator}} & \multicolumn{1}{c@{}}{\textbf{target label}} \\ 1224 1228 \begin{cfa} 1225 1229 choose ( ... ) { … … 1264 1268 \begin{figure} 1265 1269 \lstDeleteShortInline@% 1266 \begin{tabular}{@{\hspace{\parindentlnth}}l @{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}1267 \multicolumn{1}{@{\hspace{\parindentlnth}}c @{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\1270 \begin{tabular}{@{\hspace{\parindentlnth}}l|@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 1271 \multicolumn{1}{@{\hspace{\parindentlnth}}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c@{}}{\textbf{C}} \\ 1268 1272 \begin{cfa} 1269 1273 `LC:` { … … 1349 1353 \subsection{Exception Handling} 1350 1354 1351 The following framework for \CFA exception 1355 The following framework for \CFA exception-handling is in place, excluding some runtime type-information and virtual functions. 1352 1356 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}. 1353 1357 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler. … … 1360 1364 \begin{cquote} 1361 1365 \lstDeleteShortInline@% 1362 \begin{tabular}{@{}l @{\hspace{2\parindentlnth}}l@{}}1363 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\1366 \begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}} 1367 \multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c@{}}{\textbf{Termination}} \\ 1364 1368 \begin{cfa} 1365 1369 `exception R { int fix; };` … … 1477 1481 If an exception is raised and caught, the handler is run before the finally clause. 1478 1482 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated. 1479 Mimicking the @finally@ clause with mechanisms like RAII is non-trivial lywhen there are multiple types and local accesses.1483 Mimicking the @finally@ clause with mechanisms like RAII is non-trivial when there are multiple types and local accesses. 1480 1484 1481 1485 … … 1530 1534 with ( s, t ) { 1531 1535 j + k; $\C{// unambiguous, s.j + t.k}$ 1532 m = 5.0; $\C{// unambiguous, t.m = 5.0}$1533 m = 1; $\C{// unambiguous, s.m = 1}$1534 int a = m; $\C{// unambiguous, a = s.i}$1535 double b = m; $\C{// unambiguous, b = t.m}$1536 m = 5.0; $\C{// unambiguous, s.m = 5.0}$ 1537 m = 1; $\C{// unambiguous, t.m = 1}$ 1538 int a = m; $\C{// unambiguous, a = t.m }$ 1539 double b = m; $\C{// unambiguous, b = s.m}$ 1536 1540 int c = s.i + t.i; $\C{// unambiguous, qualification}$ 1537 (double)m; $\C{// unambiguous, cast }$1541 (double)m; $\C{// unambiguous, cast s.m}$ 1538 1542 } 1539 1543 \end{cfa} … … 1559 1563 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1560 1564 \begin{cfa} 1561 void ?{}( S & s, int `i` ) with ( s ) ` with( $\emph{\color{red}params}$ )` {1565 void ?{}( S & s, int `i` ) with ( s ) `{` `with( $\emph{\color{red}params}$ )` { 1562 1566 s.i = `i`; j = 3; m = 5.5; 1563 } 1567 } `}` 1564 1568 \end{cfa} 1565 1569 Finally, a cast may be used to disambiguate among overload variables in a @with@ expression: … … 1629 1633 \lstDeleteShortInline@% 1630 1634 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}} 1631 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1635 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1632 1636 \begin{cfa} 1633 1637 `[5] *` int x1; … … 1657 1661 \lstDeleteShortInline@% 1658 1662 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1659 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1663 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1660 1664 \begin{cfa} 1661 1665 `*` int x, y; 1662 int y;1663 \end{cfa} 1664 & 1665 \begin{cfa} 1666 int `*`x, `*`y ;1666 int z; 1667 \end{cfa} 1668 & 1669 \begin{cfa} 1670 int `*`x, `*`y, z; 1667 1671 1668 1672 \end{cfa} … … 1670 1674 \lstMakeShortInline@% 1671 1675 \end{cquote} 1672 The downside of the \CFA semantics is the need to separate regular and pointer declarations. 1676 % The downside of the \CFA semantics is the need to separate regular and pointer declarations. 1677 The separation of regular and pointer declarations by \CFA declarations enforces greater clarity with only slightly more syntax. 1673 1678 1674 1679 \begin{comment} … … 1677 1682 \lstDeleteShortInline@% 1678 1683 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}} 1679 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}} \\1684 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}} \\ 1680 1685 \begin{cfa} 1681 1686 [ 5 ] int z; … … 1719 1724 \lstDeleteShortInline@% 1720 1725 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}} 1721 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}} \\1726 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}} \\ 1722 1727 \begin{cfa} 1723 1728 extern const * const int x; … … 1744 1749 \lstDeleteShortInline@% 1745 1750 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1746 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1751 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1747 1752 \begin{cfa} 1748 1753 y = (* int)x; … … 1772 1777 \lstDeleteShortInline@% 1773 1778 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1774 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1779 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 1775 1780 \begin{cfa} 1776 1781 [double] foo(), foo( int ), foo( double ) {...} … … 1790 1795 * [ * int ] ( int y ) gp; $\C{// pointer to function returning pointer to int with int parameter}$ 1791 1796 * [ ] ( int, char ) hp; $\C{// pointer to function returning no result with int and char parameters}$ 1792 * [ * int, int ] ( int ) jp; $\C{// pointer to function returning pointer to int and int with int parameter}$ 1793 \end{cfa} 1794 Note, a function name cannot be specified: 1795 \begin{cfa} 1796 * [ int x ] f () fp; $\C{// function name "f" is disallowed}\CRT$ 1797 \end{cfa} 1797 * [ * int, int ] ( int ) jp; $\C{// pointer to function returning pointer to int and int with int parameter}\CRT$ 1798 \end{cfa} 1799 Note, the name of the function pointer is specified last, as for other variable declarations. 1798 1800 1799 1801 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration. … … 1852 1854 This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@. 1853 1855 Secondly, \CFA references are rebindable, whereas \CC references have a fixed address. 1854 \newsavebox{\LstBox}1855 \begin{lrbox}{\LstBox}1856 \lstset{basicstyle=\footnotesize\linespread{0.9}\sf}1857 \begin{cfa}1858 int & r = *new( int );1859 ... $\C{// non-null reference}$1860 delete &r; $\C{// unmanaged (programmer) memory-management}$1861 r += 1; $\C{// undefined reference}$1862 \end{cfa}1863 \end{lrbox}1864 1856 Rebinding allows \CFA references to be default-initialized (\eg to a null pointer\footnote{ 1865 While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations: 1866 \begin{cquote} 1867 \usebox{\LstBox} 1868 \end{cquote} 1869 }% 1870 ) and point to different addresses throughout their lifetime, like pointers. 1857 While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations, \eg using a pointer after its storage is deleted.}) and point to different addresses throughout their lifetime, like pointers. 1871 1858 Rebinding is accomplished by extending the existing syntax and semantics of the address-of operator in C. 1872 1859 … … 1880 1867 \begin{itemize} 1881 1868 \item 1882 if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) th an @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).1869 if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) then @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols). 1883 1870 1884 1871 \item … … 1914 1901 \end{cfa} 1915 1902 This allows complex values to be succinctly and efficiently passed to functions, without the syntactic overhead of explicit definition of a temporary variable or the runtime cost of pass-by-value. 1916 \CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const hell} problem, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.1903 \CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const poisoning} problem~\cite{Taylor10}, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers. 1917 1904 1918 1905 … … 1928 1915 \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}} 1929 1916 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}} & \multicolumn{1}{c|}{\textbf{C Implicit Hoisting}} & \multicolumn{1}{c}{\textbf{\CFA}} \\ 1930 \hline1931 1917 \begin{cfa} 1932 1918 struct S { … … 2008 1994 The symbol \lstinline+^+ is used for the destructor name because it was the last binary operator that could be used in a unary context.}. 2009 1995 The name @{}@ comes from the syntax for the initializer: @struct S { int i, j; } s = `{` 2, 3 `}`@. 2010 Like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @?{}(x, ...)@ or @^{}(x, ...)@.1996 Like other \CFA operators, these names represent the syntax used to explicitly call the constructor or destructor, \eg @s{...}@ or @^s{...}@. 2011 1997 The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed. 2012 1998 While the first parameter is informally called the @this@ parameter, as in object-oriented languages, any variable name may be used. 2013 Both constructors and destructors allow additional paramete s after the @this@ parameter for specifying values for initialization/de-initialization\footnote{1999 Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/de-initialization\footnote{ 2014 2000 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}. 2015 2001 \begin{cfa} … … 2018 2004 void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$ 2019 2005 { 2020 VLA x; $\C{// implicit: ?\{\}( x );}$2021 } $\C{// implicit: ?\^{}\{\}( x );}$2006 VLA x; $\C{// implicit:\ \ x\{\};}$ 2007 } $\C{// implicit:\ \textasciicircum{}x\{\};}$ 2022 2008 \end{cfa} 2023 2009 @VLA@ is a \newterm{managed type}\footnote{ … … 2044 2030 appropriate care is taken to not recursively call the copy constructor when initializing the second parameter. 2045 2031 2046 \CFA constructors may be explicitly call , like Java, and destructors may be explicitly called, like \CC.2032 \CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC. 2047 2033 Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of member fields in user-defined constructors and reuse of existing storage allocations. 2048 While existing call syntax works for explicit calls to constructors and destructors, \CFA also provides a more concise \newterm{operator syntax} for both:2034 Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls: 2049 2035 \begin{cfa} 2050 2036 { 2051 2037 VLA x, y = { 20, 0x01 }, z = y; $\C{// z points to y}$ 2052 // ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y );2038 // x{}; y{ 20, 0x01 }; z{ z, y }; 2053 2039 ^x{}; $\C{// deallocate x}$ 2054 2040 x{}; $\C{// reallocate x}$ … … 2057 2043 y{ x }; $\C{// reallocate y, points to x}$ 2058 2044 x{}; $\C{// reallocate x, not pointing to y}$ 2059 // ^?{}(z); ^?{}(y); ^?{}(x);2045 // ^z{}; ^y{}; ^x{}; 2060 2046 } 2061 2047 \end{cfa} … … 2078 2064 In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged, so implicit constructor and destructor calls are not generated. 2079 2065 Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg \lstinline|VLA a @= { 0, 0x0 }|, with the usual C initialization semantics. 2080 The same syntax can be used in a compound literal, \eg \lstinline|a = VLA`@`{ 0, 0x0 }|, to create a C-style literal.2066 The same syntax can be used in a compound literal, \eg \lstinline|a = (VLA)`@`{ 0, 0x0 }|, to create a C-style literal. 2081 2067 The point of \lstinline|@=| is to provide a migration path from legacy C code to \CFA, by providing a mechanism to incrementally convert to implicit initialization. 2082 2068 … … 2134 2120 2135 2121 In C, @0@ has the special property that it is the only ``false'' value; 2136 fromthe standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.2122 by the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true. 2137 2123 As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics. 2138 2124 Operator overloading in \CFA provides a natural means to implement this truth-value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer. … … 2169 2155 \lstDeleteShortInline@% 2170 2156 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}} 2171 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}} & \multicolumn{1}{c}{\textbf{postfix pointer}} \\2157 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}} & \multicolumn{1}{c@{}}{\textbf{postfix pointer}} \\ 2172 2158 \begin{cfa} 2173 2159 int |?`h|( int s ); … … 2214 2200 \lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2215 2201 \lstDeleteShortInline@% 2216 \begin{tabular}{@{}l@{\hspace{ 2\parindentlnth}}l@{}}2217 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\2202 \begin{tabular}{@{}l@{\hspace{1.25\parindentlnth}}l@{}} 2203 \multicolumn{1}{@{}c@{\hspace{1.25\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}} \\ 2218 2204 \begin{cfa} 2219 2205 struct W { … … 2259 2245 W w, heavy = { 20 }; 2260 2246 w = 155|_lb|; 2261 w = 0b1111|_lb|; // error,binary unsupported2247 // binary unsupported 2262 2248 w = 0${\color{red}\LstBasicStyle{'}}$233|_lb|; // quote separator 2263 2249 w = 0x9b|_kg|; … … 2289 2275 \lstDeleteShortInline@% 2290 2276 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2291 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\2277 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c@{}}{\textbf{Usage}} \\ 2292 2278 \begin{cfa} 2293 2279 const short int `MIN` = -32768; … … 2307 2293 \begin{cquote} 2308 2294 \lstDeleteShortInline@% 2309 \begin{tabular}{@{}l@{\hspace{ 2\parindentlnth}}l@{}}2310 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\2295 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2296 \multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 2311 2297 \begin{cfa} 2312 2298 MIN 2313 2314 2299 MAX 2315 2316 2300 PI 2317 2301 E … … 2319 2303 & 2320 2304 \begin{cfa} 2321 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, 2322 LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN 2323 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, 2324 LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX 2305 CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN 2306 UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX 2325 2307 M_PI, M_PIl 2326 2308 M_E, M_El … … 2338 2320 \lstDeleteShortInline@% 2339 2321 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2340 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\2322 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c@{}}{\textbf{Usage}} \\ 2341 2323 \begin{cfa} 2342 2324 float `log`( float x ); … … 2357 2339 \lstDeleteShortInline@% 2358 2340 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2359 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\2341 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 2360 2342 \begin{cfa} 2361 2343 log … … 2385 2367 \lstDeleteShortInline@% 2386 2368 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2387 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\2369 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c@{}}{\textbf{Usage}} \\ 2388 2370 \begin{cfa} 2389 2371 unsigned int `abs`( int ); … … 2404 2386 \lstDeleteShortInline@% 2405 2387 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2406 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\2388 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 2407 2389 \begin{cfa} 2408 2390 abs … … 2427 2409 an allocation with a specified character. 2428 2410 \item[resize] 2429 an existing allocation to decrease d or increasedits size.2411 an existing allocation to decrease or increase its size. 2430 2412 In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied. 2431 2413 For an increase in storage size, new storage after the copied data may be filled. … … 2441 2423 2442 2424 \begin{table} 2425 \caption{Storage-Management Operations} 2426 \label{t:StorageManagementOperations} 2443 2427 \centering 2444 2428 \lstDeleteShortInline@% … … 2460 2444 \lstDeleteShortInline~% 2461 2445 \lstMakeShortInline@% 2462 \caption{Storage-Management Operations}2463 \label{t:StorageManagementOperations}2464 2446 \end{table} 2465 2447 2466 2448 \begin{figure} 2467 2449 \centering 2468 \begin{cquote} 2469 \begin{cfa}[aboveskip=0pt] 2450 \begin{cfa}[aboveskip=0pt,xleftmargin=0pt] 2470 2451 size_t dim = 10; $\C{// array dimension}$ 2471 2452 char fill = '\xff'; $\C{// initialization fill value}$ … … 2473 2454 \end{cfa} 2474 2455 \lstDeleteShortInline@% 2475 \begin{tabular}{@{}l@{\hspace{ 2\parindentlnth}}l@{}}2476 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\2477 \begin{cfa} 2456 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2457 \multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 2458 \begin{cfa}[xleftmargin=-10pt] 2478 2459 ip = alloc(); 2479 2460 ip = alloc( fill ); … … 2490 2471 & 2491 2472 \begin{cfa} 2492 ip = (int *)malloc( sizeof( int ) ); 2493 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2494 ip = (int *)malloc( dim * sizeof( int ) ); 2495 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2496 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2497 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); 2498 memset( ip, fill, 4 * dim * sizeof( int ) ); 2499 ip = memalign( 16, sizeof( int ) ); 2500 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2501 ip = memalign( 16, dim * sizeof( int ) ); 2502 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2503 \end{cfa} 2504 \end{tabular} 2505 \lstMakeShortInline@% 2506 \end{cquote} 2473 ip = (int *)malloc( sizeof(int) ); 2474 ip = (int *)malloc( sizeof(int) ); memset( ip, fill, sizeof(int) ); 2475 ip = (int *)malloc( dim * sizeof(int) ); 2476 ip = (int *)malloc( sizeof(int) ); memset( ip, fill, dim * sizeof(int) ); 2477 ip = (int *)realloc( ip, 2 * dim * sizeof(int) ); 2478 ip = (int *)realloc( ip, 4 * dim * sizeof(int) ); memset( ip, fill, 4 * dim * sizeof(int)); 2479 2480 ip = memalign( 16, sizeof(int) ); 2481 ip = memalign( 16, sizeof(int) ); memset( ip, fill, sizeof(int) ); 2482 ip = memalign( 16, dim * sizeof(int) ); 2483 ip = memalign( 16, dim * sizeof(int) ); memset( ip, fill, dim * sizeof(int) ); 2484 \end{cfa} 2485 \end{tabular} 2486 \lstMakeShortInline@% 2507 2487 \caption{\CFA versus C Storage-Allocation} 2508 2488 \label{f:StorageAllocation} … … 2517 2497 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2518 2498 \end{cfa} 2519 Note, \CC can only initializ ationarray elements via the default constructor.2499 Note, \CC can only initialize array elements via the default constructor. 2520 2500 2521 2501 Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap. … … 2534 2514 \lstDeleteShortInline@% 2535 2515 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 2536 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\2516 \multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}} \\ 2537 2517 \begin{cfa} 2538 2518 int x = 1, y = 2, z = 3; … … 2589 2569 \end{cquote} 2590 2570 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output. 2591 2571 \begin{comment} 2592 2572 The implicit separator character (space/blank) is a separator not a terminator. 2593 2573 The rules for implicitly adding the separator are: … … 2608 2588 }% 2609 2589 \end{itemize} 2590 \end{comment} 2610 2591 There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output. 2611 2592 … … 2622 2603 \centering 2623 2604 \lstDeleteShortInline@% 2624 \begin{tabular}{@{}l@{\hspace{ 2\parindentlnth}}@{\hspace{2\parindentlnth}}l@{}}2625 \multicolumn{1}{ c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{2\parindentlnth}}c}{\textbf{C}} \\2605 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}} 2606 \multicolumn{1}{@{}c@{\hspace{3\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}} \\ 2626 2607 \begin{cfa} 2627 2608 #include <gmp> … … 2656 2637 2657 2638 2658 \section{ Evaluation}2639 \section{Polymorphism Evaluation} 2659 2640 \label{sec:eval} 2660 2641 2661 Though \CFA provides significant added functionality over C, these features have a low runtime penalty. 2662 In fact, \CFA's features for generic programming can enable faster runtime execution than idiomatic @void *@-based C code. 2663 This claim is demonstrated through a set of generic-code-based micro-benchmarks in C, \CFA, and \CC (see stack implementations in Appendix~\ref{sec:BenchmarkStackImplementations}). 2642 \CFA adds parametric polymorphism to C. 2643 A runtime evaluation is performed to compare the cost of alternative styles of polymorphism. 2644 The goal is to compare just the underlying mechanism for implementing different kinds of polymorphism. 2645 % Though \CFA provides significant added functionality over C, these features have a low runtime penalty. 2646 % In fact, it is shown that \CFA's generic programming can enable faster runtime execution than idiomatic @void *@-based C code. 2647 The experiment is a set of generic-stack micro-benchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}). 2664 2648 Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks should show little runtime variance, differing only in length and clarity of source code. 2665 2649 A more illustrative comparison measures the costs of idiomatic usage of each language's features. … … 2692 2676 \end{figure} 2693 2677 2694 The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with the presented features, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.2678 The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with parametric polymorphism, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV. 2695 2679 The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface; 2696 2680 hence runtime checks are necessary to safely down-cast objects. 2697 2681 The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while C and \CCV lack such a capability and instead must store generic objects via pointers to separately-allocated objects. 2698 Note that the C benchmark uses unchecked casts as there is no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.2682 Note, the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically. 2699 2683 2700 2684 Figure~\ref{fig:eval} and Table~\ref{tab:eval} show the results of running the benchmark in Figure~\ref{fig:BenchmarkTest} and its C, \CC, and \CCV equivalents. … … 2711 2695 2712 2696 \begin{table} 2713 \centering2714 2697 \caption{Properties of benchmark code} 2715 2698 \label{tab:eval} 2699 \centering 2716 2700 \newcommand{\CT}[1]{\multicolumn{1}{c}{#1}} 2717 2701 \begin{tabular}{rrrrr} … … 2726 2710 The C and \CCV variants are generally the slowest with the largest memory footprint, because of their less-efficient memory layout and the pointer-indirection necessary to implement generic types; 2727 2711 this inefficiency is exacerbated by the second level of generic types in the pair benchmarks. 2728 By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair of @short@ and @char@ because the storage layout is equivalent, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.2712 By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair because of equivalent storage layout, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead. 2729 2713 \CCV is slower than C largely due to the cost of runtime type-checking of down-casts (implemented with @dynamic_cast@); 2730 The outlier in the graph for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code. 2731 The gcc compiler is unable to optimize some dead code and condense nested calls; a compiler designed for \CFA could easily perform these optimizations. 2714 The outlier for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code. 2715 The gcc compiler is unable to optimize some dead code and condense nested calls; 2716 a compiler designed for \CFA could easily perform these optimizations. 2732 2717 Finally, the binary size for \CFA is larger because of static linking with the \CFA libraries. 2733 2718 … … 2741 2726 Line-count is a fairly rough measure of code complexity; 2742 2727 another important factor is how much type information the programmer must specify manually, especially where that information is not compiler-checked. 2743 Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un type-checked downcasts, \eg @object@ to @integer@ when popping a stack.2728 Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts, \eg @object@ to @integer@ when popping a stack. 2744 2729 To quantify this manual typing, the ``redundant type annotations'' line in Table~\ref{tab:eval} counts the number of lines on which the type of a known variable is respecified, either as a format specifier, explicit downcast, type-specific function, or by name in a @sizeof@, struct literal, or @new@ expression. 2745 2730 The \CC benchmark uses two redundant type annotations to create a new stack nodes, while the C and \CCV benchmarks have several such annotations spread throughout their code. 2746 2731 The \CFA benchmark is able to eliminate all redundant type annotations through use of the polymorphic @alloc@ function discussed in Section~\ref{sec:libraries}. 2747 2732 2733 We conjecture these results scale across most generic data-types as the underlying polymorphism implement is constant. 2734 2748 2735 2749 2736 \section{Related Work} … … 2751 2738 2752 2739 \subsection{Polymorphism} 2740 2741 ML~\cite{ML} was the first language to support parametric polymorphism. 2742 Like \CFA, it supports universal type parameters, but not the use of assertions and traits to constrain type arguments. 2743 Haskell~\cite{Haskell10} combines ML-style polymorphism, polymorphic data types, and type inference with the notion of type classes, collections of overloadable methods that correspond in intent to traits in \CFA. 2744 Unlike \CFA, Haskell requires an explicit association between types and their classes that specifies the implementation of operations. 2745 These associations determine the functions that are assertion arguments for particular combinations of class and type, in contrast to \CFA where the assertion arguments are selected at function call sites based upon the set of operations in scope at that point. 2746 Haskell also severely restricts the use of overloading: an overloaded name can only be associated with a single class, and methods with overloaded names can only be defined as part of instance declarations. 2753 2747 2754 2748 \CC provides three disjoint polymorphic extensions to C: overloading, inheritance, and templates. … … 2804 2798 Go does not have tuples but supports MRVF. 2805 2799 Java's variadic functions appear similar to C's but are type-safe using homogeneous arrays, which are less useful than \CFA's heterogeneously-typed variadic functions. 2806 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml} and~\cite{Scala}, which decompose tuples using pattern matching.2800 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml}, Haskell, and Scala~\cite{Scala}, which decompose tuples using pattern matching. 2807 2801 2808 2802 … … 2835 2829 Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable. 2836 2830 2837 There is ongoing work on a wide range of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, concurrent primitives, and modules. 2838 While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these extensions. 2839 There are also interesting future directions for the polymorphism design. 2840 Notably, \CC template functions trade compile time and code bloat for optimal runtime of individual instantiations of polymorphic functions. 2841 \CFA polymorphic functions use dynamic virtual-dispatch; 2842 the runtime overhead of this approach is low, but not as low as inlining, and it may be beneficial to provide a mechanism for performance-sensitive code. 2831 While all examples in the paper compile and run, a public beta-release of \CFA will take 6--8 months to reduce compilation time, provide better debugging, and add a few more libraries. 2832 There is also new work on a number of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, and modules. 2833 While \CFA polymorphic functions use dynamic virtual-dispatch with low runtime overhead (see Section~\ref{sec:eval}), it is not as low as \CC template-inlining. 2834 Hence it may be beneficial to provide a mechanism for performance-sensitive code. 2843 2835 Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types (\CC template specialization). 2844 2836 These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat. … … 2849 2841 2850 2842 The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, Andrew Beach and Brice Dobry on the features described in this paper, and thank Magnus Madsen for feedback on the writing. 2851 This work is supported by a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada. 2852 2853 2843 Funding for this project has been provided by Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada. 2844 2845 {% 2846 \fontsize{9bp}{12bp}\selectfont% 2854 2847 \bibliography{pl} 2855 2848 }% 2856 2849 2857 2850 \appendix -
doc/papers/general/evaluation/timing.gp
r7d0a3ba r358cba0 25 25 26 26 set label "23.9" at 7.125,10.5 27 27 set style fill pattern 4 border lt -1 28 28 # set datafile separator "," 29 29 plot for [COL=2:5] 'evaluation/timing.dat' using (column(COL)/SCALE):xticlabels(1) title columnheader -
src/CodeGen/CodeGenerator.cc
r7d0a3ba r358cba0 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S un Sep 3 20:42:52 201713 // Update Count : 49 012 // Last Modified On : Sat May 5 09:08:32 2018 13 // Update Count : 494 14 14 // 15 15 #include "CodeGenerator.h" … … 370 370 371 371 void CodeGenerator::postvisit( Constant * constant ) { 372 output << constant->get_value() 372 output << constant->get_value(); 373 373 } 374 374 … … 587 587 output << "("; 588 588 if ( castExpr->get_result()->isVoid() ) { 589 output << "(void)" 589 output << "(void)"; 590 590 } else { 591 591 // at least one result type of cast. … … 878 878 } // for 879 879 } // if 880 output << " );" 880 output << " );"; 881 881 } 882 882 … … 886 886 output << "( "; 887 887 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor ); 888 output << " )" 888 output << " )"; 889 889 } 890 890 891 891 void CodeGenerator::postvisit( DirectiveStmt * dirStmt ) { 892 output << dirStmt->directive;892 output << endl << dirStmt->directive; // endl prevents spaces before directive 893 893 } 894 894 … … 907 907 908 908 void CodeGenerator::postvisit( SwitchStmt * switchStmt ) { 909 output << "switch ( " 909 output << "switch ( "; 910 910 switchStmt->get_condition()->accept( *visitor ); 911 911 output << " ) "; … … 933 933 ++indent; 934 934 for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end(); i++) { 935 output << indent << printLabels( (*i)->get_labels() ) 935 output << indent << printLabels( (*i)->get_labels() ) ; 936 936 (*i)->accept( *visitor ); 937 937 output << endl; … … 1070 1070 void CodeGenerator::postvisit( WhileStmt * whileStmt ) { 1071 1071 if ( whileStmt->get_isDoWhile() ) { 1072 output << "do" 1073 } else { 1074 output << "while (" 1072 output << "do"; 1073 } else { 1074 output << "while ("; 1075 1075 whileStmt->get_condition()->accept( *visitor ); 1076 1076 output << ")"; … … 1084 1084 1085 1085 if ( whileStmt->get_isDoWhile() ) { 1086 output << " while (" 1086 output << " while ("; 1087 1087 whileStmt->get_condition()->accept( *visitor ); 1088 1088 output << ");"; -
src/CodeGen/FixNames.cc
r7d0a3ba r358cba0 56 56 auto && name = SymTab::Mangler::mangle( mainDecl.get() ); 57 57 // std::cerr << name << std::endl; 58 return name;58 return std::move(name); 59 59 } 60 60 std::string mangle_main_args() { … … 79 79 auto&& name = SymTab::Mangler::mangle( mainDecl.get() ); 80 80 // std::cerr << name << std::endl; 81 return name;81 return std::move(name); 82 82 } 83 83 -
src/Common/Heap.cc
r7d0a3ba r358cba0 7 7 // Heap.cc -- 8 8 // 9 // Author : Peter A. Buhr10 // Created On : 9 // Author : Thierry Delisle 10 // Created On : Thu May 3 16:16:10 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu May 3 16:16:10201813 // Update Count : 2 12 // Last Modified On : Fri May 4 17:27:31 2018 13 // Update Count : 28 14 14 // 15 15 16 namespace HeapStats{ 17 void newPass( const char * const name ) {} 18 void printStats() {} 16 #include <cassert> 17 #include <cmath> 18 #include <cstddef> 19 #include <cstring> 20 #include <iomanip> 21 #include <iostream> 22 23 //#define WITH_HEAP_STATISTICS 24 25 namespace HeapStats { 26 #if !defined( WITH_HEAP_STATISTICS ) 27 void newPass( const char * const ) {} 28 29 void printStats() {} 30 #else 31 struct StatBlock { 32 const char * name = nullptr; 33 size_t mallocs = 0; 34 size_t frees = 0; 35 }; 36 37 StatBlock passes[100] = {{ "Pre-Parse", 0, 0 }}; 38 const size_t passes_size = sizeof(passes) / sizeof(passes[0]); 39 size_t passes_cnt = 1; 40 41 void newPass( const char * const name ) { 42 passes[passes_cnt].name = name; 43 passes[passes_cnt].mallocs = 0; 44 passes[passes_cnt].frees = 0; 45 passes_cnt++; 46 47 assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h"); 48 } 49 50 void print(size_t value, size_t total) { 51 std::cerr << std::setw(12) << value; 52 std::cerr << "(" << std::setw(3); 53 std::cerr << (value == 0 ? 0 : value * 100 / total); 54 std::cerr << "%) | "; 55 } 56 57 void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) { 58 std::cerr << std::setw(nc) << stat.name; 59 std::cerr << " | "; 60 61 print(stat.mallocs, total_mallocs); 62 print(stat.frees , total_frees ); 63 std::cerr << "\n"; 64 } 65 66 void print(char c, size_t nc) { 67 for(size_t i = 0; i < nc; i++) { 68 std::cerr << c; 69 } 70 std::cerr << '\n'; 71 } 72 73 void printStats() { 74 size_t nc = 0; 75 size_t total_mallocs = 0; 76 size_t total_frees = 0; 77 for(size_t i = 0; i < passes_cnt; i++) { 78 nc = std::max(nc, std::strlen(passes[i].name)); 79 total_mallocs += passes[i].mallocs; 80 total_frees += passes[i].frees; 81 } 82 size_t nct = nc + 44; 83 84 const char * const title = "Heap Usage Statistic"; 85 print('=', nct); 86 for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' '; 87 std::cerr << title << std::endl; 88 print('-', nct); 89 std::cerr << std::setw(nc) << "Pass"; 90 std::cerr << " | Malloc Count | Free Count |" << std::endl; 91 92 print('-', nct); 93 for(size_t i = 0; i < passes_cnt; i++) { 94 print(passes[i], nc, total_mallocs, total_frees); 95 } 96 print('-', nct); 97 print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees); 98 99 } 100 101 #include <stdarg.h> 102 #include <stddef.h> 103 #include <stdio.h> 104 #include <string.h> 105 #include <unistd.h> 106 #include <signal.h> 107 extern "C" { 108 #include <dlfcn.h> 109 #include <execinfo.h> 110 } 111 112 //============================================================================================= 113 // Interposing helpers 114 //============================================================================================= 115 116 typedef void (* generic_fptr_t)(void); 117 generic_fptr_t interpose_symbol( const char * symbol, const char * version ) { 118 const char * error; 119 120 static void * library; 121 if ( ! library ) { 122 #if defined( RTLD_NEXT ) 123 library = RTLD_NEXT; 124 #else 125 // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ 126 library = dlopen( "libc.so.6", RTLD_LAZY ); 127 error = dlerror(); 128 if ( error ) { 129 std::cerr << "interpose_symbol : failed to open libc, " << error << std::endl; 130 abort(); 131 } 132 #endif // RTLD_NEXT 133 } // if 134 135 generic_fptr_t fptr; 136 137 #if defined( _GNU_SOURCE ) 138 if ( version ) { 139 fptr = (generic_fptr_t)dlvsym( library, symbol, version ); 140 } else { 141 fptr = (generic_fptr_t)dlsym( library, symbol ); 142 } 143 #else 144 fptr = (generic_fptr_t)dlsym( library, symbol ); 145 #endif // _GNU_SOURCE 146 147 error = dlerror(); 148 if ( error ) { 149 std::cerr << "interpose_symbol : internal error, " << error << std::endl; 150 abort(); 151 } 152 153 return fptr; 154 } 155 156 extern "C" { 157 void * malloc( size_t size ) __attribute__((malloc)); 158 void * malloc( size_t size ) { 159 static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr )); 160 if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++; 161 return __malloc( size ); 162 } 163 164 void free( void * ptr ) { 165 static auto __free = reinterpret_cast<void (*)(void *)>(interpose_symbol( "free", nullptr )); 166 if( passes_cnt > 0 ) passes[passes_cnt - 1].frees++; 167 return __free( ptr ); 168 } 169 170 void * calloc( size_t nelem, size_t size ) { 171 static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr )); 172 if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++; 173 return __calloc( nelem, size ); 174 } 175 176 void * realloc( void * ptr, size_t size ) { 177 static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr )); 178 void * s = __realloc( ptr, size ); 179 if ( s != ptr && passes_cnt > 0 ) { // did realloc get new storage ? 180 passes[passes_cnt - 1].mallocs++; 181 passes[passes_cnt - 1].frees++; 182 } // if 183 return s; 184 } 185 } 186 #endif 19 187 } 20 -
src/Common/Heap.h
r7d0a3ba r358cba0 7 7 // Heap.h -- 8 8 // 9 // Author : Peter A. Buhr10 // Created On : 9 // Author : Thierry Delisle 10 // Created On : Thu May 3 16:16:10 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu May 3 16:16:10201813 // Update Count : 212 // Last Modified On : Fri May 4 14:34:08 2018 13 // Update Count : 3 14 14 // 15 15 … … 17 17 18 18 namespace HeapStats { 19 20 19 void newPass( const char * const name ); 20 void printStats(); 21 21 } -
src/Common/PassVisitor.proto.h
r7d0a3ba r358cba0 47 47 48 48 operator bool() { return m_ref ? *m_ref : true; } 49 bool operator=( bool val ) { return *m_ref = val; }49 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 50 50 51 51 private: … … 53 53 friend class ChildrenGuard; 54 54 55 bool * set( bool &val ) {55 bool * set( bool * val ) { 56 56 bool * prev = m_ref; 57 m_ref = &val;57 m_ref = val; 58 58 return prev; 59 59 } … … 67 67 ChildrenGuard( bool_ref * ref ) 68 68 : m_val ( true ) 69 , m_prev( ref ? ref->set( m_val ) : nullptr )69 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 70 70 , m_ref ( ref ) 71 71 {} … … 73 73 ~ChildrenGuard() { 74 74 if( m_ref ) { 75 m_ref->set( *m_prev );75 m_ref->set( m_prev ); 76 76 } 77 77 } -
src/Common/utility.h
r7d0a3ba r358cba0 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu May 3 12:18:31201813 // Update Count : 3912 // Last Modified On : Sun May 6 22:24:16 2018 13 // Update Count : 40 14 14 // 15 15 … … 442 442 template<typename T> 443 443 inline 444 #if __GNUC__ > 4444 #if defined(__GNUC__) && __GNUC__ > 4 445 445 constexpr 446 446 #endif -
src/Parser/parser.yy
r7d0a3ba r358cba0 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu May 3 08:20:09201813 // Update Count : 32 2512 // Last Modified On : Fri May 11 17:51:38 2018 13 // Update Count : 3261 14 14 // 15 15 … … 302 302 303 303 %type<decl> field_declaration field_declaration_list field_declarator field_declaring_list 304 %type<en> field field_list field_name fraction_constants 304 %type<en> field field_list field_name fraction_constants_opt 305 305 306 306 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 499 499 | type_name '.' no_attr_identifier // CFA, nested type 500 500 { SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } 501 // { $$ = nullptr; } 501 502 | type_name '.' '[' push field_list pop ']' // CFA, nested type / tuple field selector 502 503 { SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } 504 // { $$ = nullptr; } 503 505 | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11 504 506 { SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; } … … 533 535 | postfix_expression '.' no_attr_identifier 534 536 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); } 537 | postfix_expression '.' INTEGERconstant // CFA, tuple index 538 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); } 539 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index 540 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); } 535 541 | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector 536 542 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $5 ) ) ); } 537 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index538 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }539 543 | postfix_expression ARROW no_attr_identifier 540 544 { 541 545 $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) ); 542 546 } 543 | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector544 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }545 547 | postfix_expression ARROW INTEGERconstant // CFA, tuple index 546 548 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); } 549 | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector 550 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); } 547 551 | postfix_expression ICR 548 552 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); } … … 597 601 598 602 field_name: 599 INTEGERconstant fraction_constants 603 INTEGERconstant fraction_constants_opt 600 604 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); } 601 | FLOATINGconstant fraction_constants 605 | FLOATINGconstant fraction_constants_opt 602 606 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); } 603 | no_attr_identifier fraction_constants 607 | no_attr_identifier fraction_constants_opt 604 608 { 605 609 $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) ); … … 607 611 ; 608 612 609 fraction_constants :613 fraction_constants_opt: 610 614 // empty 611 615 { $$ = nullptr; } 612 | fraction_constants FLOATING_FRACTIONconstant616 | fraction_constants_opt FLOATING_FRACTIONconstant 613 617 { 614 618 Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 ); … … 2390 2394 external_definition_list: 2391 2395 external_definition 2392 | external_definition_list { forall = xxx; } push external_definition 2396 | external_definition_list 2397 { forall = xxx; } 2398 push external_definition 2393 2399 { $$ = $1 ? $1->appendList( $4 ) : $4; } 2394 2400 ; … … 2430 2436 { 2431 2437 for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) { 2432 iter->addQualifiers( $1->clone() ); 2438 if ( isMangled( iter->linkage ) ) { // ignore extern "C" 2439 iter->addQualifiers( $1->clone() ); 2440 } // if 2433 2441 } // for 2434 2442 xxx = false; … … 2443 2451 { 2444 2452 for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) { 2445 iter->addQualifiers( $1->clone() ); 2453 if ( isMangled( iter->linkage ) ) { // ignore extern "C" 2454 iter->addQualifiers( $1->clone() ); 2455 } // if 2446 2456 } // for 2447 2457 xxx = false; … … 2457 2467 { 2458 2468 for ( DeclarationNode * iter = $6; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) { 2459 iter->addQualifiers( $1->clone() ); 2460 iter->addQualifiers( $2->clone() ); 2469 if ( isMangled( iter->linkage ) && isMangled( $2->linkage ) ) { // ignore extern "C" 2470 iter->addQualifiers( $1->clone() ); 2471 iter->addQualifiers( $2->clone() ); 2472 } // if 2461 2473 } // for 2462 2474 xxx = false; -
src/benchmark/Makefile.am
r7d0a3ba r358cba0 43 43 44 44 %.runquiet : 45 @+make $(basename $@) 45 @+make $(basename $@) CFLAGS="-w" 46 46 @taskset -c 1 ./a.out 47 47 @rm -f a.out -
src/benchmark/Makefile.in
r7d0a3ba r358cba0 459 459 460 460 %.runquiet : 461 @+make $(basename $@) 461 @+make $(basename $@) CFLAGS="-w" 462 462 @taskset -c 1 ./a.out 463 463 @rm -f a.out -
src/driver/cc1.cc
r7d0a3ba r358cba0 10 10 // Created On : Fri Aug 26 14:23:51 2005 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 18 08:14:21 201713 // Update Count : 8112 // Last Modified On : Sat May 12 16:11:53 2018 13 // Update Count : 94 14 14 // 15 15 … … 32 32 string compiler_name( CFA_BACKEND_CC ); // path/name of C compiler 33 33 34 string D__GCC_X__( "-D__GCC_X__=" ); 34 35 string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" ); 35 36 string D__CFA_FLAGPREFIX__( "-D__CFA_FLAG__=" ); … … 162 163 cargs[ncargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str(); 163 164 ncargs += 1; 165 i += 1; // and the argument 166 } else if ( prefix( arg, D__GCC_X__ ) ) { 167 args[nargs] = "-x"; 168 nargs += 1; 169 args[nargs] = ( *new string( arg.substr( D__GCC_X__.size() ) ) ).c_str(); // pass the flag along 170 nargs += 1; 171 } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_X__.substr(2) ) ) { 172 args[nargs] = "-x"; 173 nargs += 1; 174 args[nargs] = ( *new string( string( argv[i + 1] ).substr( D__GCC_X__.size() - 2 ) ) ).c_str(); // pass the flag along 175 nargs += 1; 164 176 i += 1; // and the argument 165 177 } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) { -
src/driver/cfa.cc
r7d0a3ba r358cba0 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 2 17:57:43201813 // Update Count : 2 2412 // Last Modified On : Mon May 14 07:52:50 2018 13 // Update Count : 243 14 14 // 15 15 … … 158 158 args[nargs] = argv[i]; // pass the argument along 159 159 nargs += 1; 160 } else if ( prefix( arg, "-std=" ) ) {160 } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) { 161 161 std_flag = true; // -std=XX provided 162 162 args[nargs] = argv[i]; // pass the argument along 163 nargs += 1; 164 } else if ( arg == "-x" ) { // lost so force along 165 args[nargs] = argv[i]; // pass the argument along 166 nargs += 1; 167 i += 1; // advance to argument 168 args[nargs] = argv[i]; // pass the argument along 169 nargs += 1; 170 args[nargs] = ( *new string( string("-D__GCC_X__=") + argv[i] ) ).c_str(); // add the argument for -x 171 nargs += 1; 172 } else if ( prefix( arg, "-x" ) ) { // lost so force along 173 args[nargs] = argv[i]; // pass the argument along 174 nargs += 1; 175 args[nargs] = ( *new string( string("-D__GCC_X__=") + arg.substr(2) ) ).c_str(); // add the argument for -x 163 176 nargs += 1; 164 177 } else if ( arg == "-w" ) { … … 240 253 } // for 241 254 255 #ifdef __x86_64__ 256 args[nargs] = "-mcx16"; // allow double-wide CAA 257 nargs += 1; 258 #endif // __x86_64__ 259 242 260 #ifdef __DEBUG_H__ 243 261 cerr << "args:"; … … 268 286 if ( link ) { 269 287 #if ! defined(HAVE_LIBCFA_RELEASE) 270 if ( !debug ) {288 if ( ! debug ) { 271 289 cerr << "error: Option -nodebug is unavailable, libcfa was not installed." << endl; 272 290 exit( EXIT_FAILURE ); 273 }291 } // if 274 292 #endif 275 293 #if ! defined(HAVE_LIBCFA_DEBUG) 276 if ( debug ) {294 if ( debug ) { 277 295 cerr << "error: Option -debug is unavailable, libcfa-d was not installed." << endl; 278 296 exit( EXIT_FAILURE ); 279 }297 } // if 280 298 #endif 281 299 … … 292 310 args[nargs] = "-L" CFA_LIBDIR; 293 311 nargs += 1; 294 if ( debug ) {312 if ( debug ) { 295 313 args[nargs] = "-lcfa-d"; 296 314 } else { 297 315 args[nargs] = "-lcfa"; 298 } 316 } // if 299 317 nargs += 1; 300 318 args[nargs] = "-lpthread"; -
src/libcfa/bits/containers.h
r7d0a3ba r358cba0 186 186 #endif 187 187 188 189 //----------------------------------------------------------------------------- 190 // Doubly Linked List 191 //----------------------------------------------------------------------------- 192 #ifdef __cforall 193 forall(dtype TYPE | sized(TYPE)) 194 #define T TYPE 195 #define __getter_t * [T * & next, T * & prev] ( T & ) 196 #else 197 typedef void (*__generit_c_getter_t)(); 198 #define T void 199 #define __getter_t __generit_c_getter_t 200 #endif 201 struct __dllist { 202 T * head; 203 __getter_t __get; 204 }; 205 #undef T 206 #undef __getter_t 207 208 #ifdef __cforall 209 #define __dllist_t(T) __dllist(T) 210 #else 211 #define __dllist_t(T) struct __dllist 212 #endif 213 214 #ifdef __cforall 215 216 forall(dtype T | sized(T)) 217 static inline [void] ?{}( __dllist(T) & this, * [T * & next, T * & prev] ( T & ) __get ) { 218 this.head{ NULL }; 219 this.__get = __get; 220 } 221 222 #define _next .0 223 #define _prev .1 224 forall(dtype T | sized(T)) 225 static inline void push_front( __dllist(T) & this, T & node ) with( this ) { 226 if ( head ) { 227 __get( node )_next = head; 228 __get( node )_prev = __get( *head )_prev; 229 // inserted node must be consistent before it is seen 230 // prevent code movement across barrier 231 asm( "" : : : "memory" ); 232 __get( *head )_prev = &node; 233 T & prev = *__get( node )_prev; 234 __get( prev )_next = &node; 235 } 236 else { 237 __get( node )_next = &node; 238 __get( node )_prev = &node; 239 } 240 241 // prevent code movement across barrier 242 asm( "" : : : "memory" ); 243 head = &node; 244 } 245 246 forall(dtype T | sized(T)) 247 static inline void remove( __dllist(T) & this, T & node ) with( this ) { 248 if ( &node == head ) { 249 if ( __get( *head )_next == head ) { 250 head = NULL; 251 } 252 else { 253 head = __get( *head )_next; 254 } 255 } 256 __get( *__get( node )_next )_prev = __get( node )_prev; 257 __get( *__get( node )_prev )_next = __get( node )_next; 258 __get( node )_next = NULL; 259 __get( node )_prev = NULL; 260 } 261 #undef _next 262 #undef _prev 263 #endif 264 188 265 //----------------------------------------------------------------------------- 189 266 // Tools -
src/libcfa/concurrency/coroutine
r7d0a3ba r358cba0 72 72 // Suspend implementation inlined for performance 73 73 static inline void suspend() { 74 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 74 // optimization : read TLS once and reuse it 75 // Safety note: this is preemption safe since if 76 // preemption occurs after this line, the pointer 77 // will also migrate which means this value will 78 // stay in syn with the TLS 79 coroutine_desc * src = TL_GET( this_coroutine ); 75 80 76 81 assertf( src->last != 0, … … 89 94 forall(dtype T | is_coroutine(T)) 90 95 static inline void resume(T & cor) { 91 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 96 // optimization : read TLS once and reuse it 97 // Safety note: this is preemption safe since if 98 // preemption occurs after this line, the pointer 99 // will also migrate which means this value will 100 // stay in syn with the TLS 101 coroutine_desc * src = TL_GET( this_coroutine ); 92 102 coroutine_desc * dst = get_coroutine(cor); 93 103 … … 107 117 dst->last = src; 108 118 dst->starter = dst->starter ? dst->starter : src; 109 } // if119 } 110 120 111 121 // always done for performance testing … … 114 124 115 125 static inline void resume(coroutine_desc * dst) { 116 coroutine_desc * src = TL_GET( this_coroutine ); // optimization 126 // optimization : read TLS once and reuse it 127 // Safety note: this is preemption safe since if 128 // preemption occurs after this line, the pointer 129 // will also migrate which means this value will 130 // stay in syn with the TLS 131 coroutine_desc * src = TL_GET( this_coroutine ); 117 132 118 133 // not resuming self ? … … 125 140 // set last resumer 126 141 dst->last = src; 127 } // if142 } 128 143 129 144 // always done for performance testing -
src/libcfa/concurrency/coroutine.c
r7d0a3ba r358cba0 84 84 // Wrapper for co 85 85 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 86 verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate ); 86 // Safety note : This could cause some false positives due to preemption 87 verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate ); 87 88 disable_interrupts(); 88 89 … … 91 92 92 93 // set new coroutine that task is executing 93 TL_SET( this_coroutine, dst );94 kernelTLS.this_coroutine = dst; 94 95 95 96 // context switch to specified coroutine … … 102 103 103 104 enable_interrupts( __cfaabi_dbg_ctx ); 104 verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate ); 105 // Safety note : This could cause some false positives due to preemption 106 verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate ); 105 107 } //ctxSwitchDirect 106 108 -
src/libcfa/concurrency/invoke.c
r7d0a3ba r358cba0 69 69 // Fetch the thread handle from the user defined thread structure 70 70 struct thread_desc* thrd = get_thread( this ); 71 thrd->self_cor.last = NULL; 71 72 72 73 // Officially start the thread by enabling preemption -
src/libcfa/concurrency/invoke.h
r7d0a3ba r358cba0 18 18 #include "bits/locks.h" 19 19 20 #define TL_GET( member ) kernelT hreadData.member21 #define TL_SET( member, value ) kernelT hreadData.member = value;20 #define TL_GET( member ) kernelTLS.member 21 #define TL_SET( member, value ) kernelTLS.member = value; 22 22 23 23 #ifdef __cforall … … 44 44 volatile bool in_progress; 45 45 } preemption_state; 46 } kernelT hreadData;46 } kernelTLS; 47 47 } 48 48 49 49 static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); } 50 static inline struct thread_desc * volatile active_thread() { return TL_GET( this_thread); }51 static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); }50 static inline struct thread_desc * volatile active_thread () { return TL_GET( this_thread ); } 51 static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE 52 52 #endif 53 53 … … 136 136 struct thread_desc * next; 137 137 138 __cfaabi_dbg_debug_do( 139 // instrusive link field for debugging 140 struct thread_desc * dbg_next; 141 struct thread_desc * dbg_prev; 142 ) 138 struct { 139 struct thread_desc * next; 140 struct thread_desc * prev; 141 } node; 143 142 }; 144 143 … … 147 146 static inline thread_desc * & get_next( thread_desc & this ) { 148 147 return this.next; 148 } 149 150 static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) { 151 return this.node.[next, prev]; 149 152 } 150 153 -
src/libcfa/concurrency/kernel
r7d0a3ba r358cba0 40 40 41 41 //----------------------------------------------------------------------------- 42 // Cluster 43 struct cluster { 44 // Ready queue locks 45 __spinlock_t ready_queue_lock; 42 // Processor 43 extern struct cluster * mainCluster; 46 44 47 // Ready queue for threads48 __queue_t(thread_desc) ready_queue;49 50 // Name of the cluster51 const char * name;52 53 // Preemption rate on this cluster54 Duration preemption_rate;55 };56 57 extern struct cluster * mainCluster;58 extern Duration default_preemption();59 60 void ?{} (cluster & this, const char * name, Duration preemption_rate);61 void ^?{}(cluster & this);62 63 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; }64 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }65 static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; }66 67 //-----------------------------------------------------------------------------68 // Processor69 45 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule }; 70 46 … … 98 74 99 75 // Cluster from which to get threads 100 cluster * cltr;76 struct cluster * cltr; 101 77 102 78 // Name of the processor … … 124 100 bool pending_preemption; 125 101 102 // Idle lock 103 104 // Link lists fields 105 struct { 106 struct processor * next; 107 struct processor * prev; 108 } node; 109 126 110 #ifdef __CFA_DEBUG__ 127 111 // Last function to enable preemption on this processor … … 130 114 }; 131 115 132 void ?{}(processor & this, const char * name, cluster & cltr);116 void ?{}(processor & this, const char * name, struct cluster & cltr); 133 117 void ^?{}(processor & this); 134 118 135 119 static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } 136 static inline void ?{}(processor & this, cluster & cltr) { this{ "Anonymous Processor", cltr}; }120 static inline void ?{}(processor & this, struct cluster & cltr) { this{ "Anonymous Processor", cltr}; } 137 121 static inline void ?{}(processor & this, const char * name) { this{name, *mainCluster }; } 122 123 static inline [processor *&, processor *& ] __get( processor & this ) { 124 return this.node.[next, prev]; 125 } 126 127 //----------------------------------------------------------------------------- 128 // Cluster 129 struct cluster { 130 // Ready queue locks 131 __spinlock_t ready_queue_lock; 132 133 // Ready queue for threads 134 __queue_t(thread_desc) ready_queue; 135 136 // Name of the cluster 137 const char * name; 138 139 // Preemption rate on this cluster 140 Duration preemption_rate; 141 142 // List of processors 143 __spinlock_t proc_list_lock; 144 __dllist_t(struct processor) procs; 145 __dllist_t(struct processor) idles; 146 147 // Link lists fields 148 struct { 149 cluster * next; 150 cluster * prev; 151 } node; 152 }; 153 extern Duration default_preemption(); 154 155 void ?{} (cluster & this, const char * name, Duration preemption_rate); 156 void ^?{}(cluster & this); 157 158 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } 159 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; } 160 static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; } 161 162 static inline [cluster *&, cluster *& ] __get( cluster & this ) { 163 return this.node.[next, prev]; 164 } 138 165 139 166 // Local Variables: // -
src/libcfa/concurrency/kernel.c
r7d0a3ba r358cba0 49 49 thread_desc * mainThread; 50 50 51 struct { __dllist_t(thread_desc) list; __spinlock_t lock; } global_threads ; 52 struct { __dllist_t(cluster ) list; __spinlock_t lock; } global_clusters; 53 51 54 //----------------------------------------------------------------------------- 52 55 // Global state … … 56 59 // volatile thread_local unsigned short disable_preempt_count = 1; 57 60 58 thread_local struct KernelThreadData kernelT hreadData= {61 thread_local struct KernelThreadData kernelTLS = { 59 62 NULL, 60 63 NULL, … … 117 120 self_mon_p = &self_mon; 118 121 next = NULL; 119 __cfaabi_dbg_debug_do( 120 dbg_next = NULL; 121 dbg_prev = NULL; 122 __cfaabi_dbg_thread_register(&this); 123 ) 122 123 node.next = NULL; 124 node.prev = NULL; 125 doregister(this); 124 126 125 127 monitors{ &self_mon_p, 1, (fptr_t)0 }; … … 155 157 terminate(&this); 156 158 verify(this.do_terminate); 157 verify( TL_GET( this_processor )!= &this);159 verify( kernelTLS.this_processor != &this); 158 160 P( terminated ); 159 verify( TL_GET( this_processor )!= &this);161 verify( kernelTLS.this_processor != &this); 160 162 pthread_join( kernel_thread, NULL ); 161 163 } … … 167 169 ready_queue{}; 168 170 ready_queue_lock{}; 171 172 procs{ __get }; 173 idles{ __get }; 174 175 doregister(this); 169 176 } 170 177 171 178 void ^?{}(cluster & this) { 172 179 unregister(this); 173 180 } 174 181 … … 183 190 __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this); 184 191 192 doregister(this->cltr, this); 193 185 194 { 186 195 // Setup preemption data … … 196 205 if(readyThread) 197 206 { 198 verify( ! TL_GET( preemption_state ).enabled );207 verify( ! kernelTLS.preemption_state.enabled ); 199 208 200 209 runThread(this, readyThread); 201 210 202 verify( ! TL_GET( preemption_state ).enabled );211 verify( ! kernelTLS.preemption_state.enabled ); 203 212 204 213 //Some actions need to be taken from the kernel … … 216 225 } 217 226 227 unregister(this->cltr, this); 228 218 229 V( this->terminated ); 219 230 … … 221 232 } 222 233 234 // KERNEL ONLY 223 235 // runThread runs a thread by context switching 224 236 // from the processor coroutine to the target thread … … 228 240 coroutine_desc * thrd_cor = dst->curr_cor; 229 241 230 // Reset the terminating actions here242 // Reset the terminating actions here 231 243 this->finish.action_code = No_Action; 232 244 233 // Update global state234 TL_SET( this_thread, dst );245 // Update global state 246 kernelTLS.this_thread = dst; 235 247 236 248 // Context Switch to the thread … … 239 251 } 240 252 253 // KERNEL_ONLY 241 254 void returnToKernel() { 242 coroutine_desc * proc_cor = get_coroutine( TL_GET( this_processor )->runner);243 coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine );255 coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 256 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine; 244 257 ThreadCtxSwitch(thrd_cor, proc_cor); 245 258 } 246 259 260 // KERNEL_ONLY 247 261 // Once a thread has finished running, some of 248 262 // its final actions must be executed from the kernel 249 263 void finishRunning(processor * this) with( this->finish ) { 250 264 if( action_code == Release ) { 251 verify( ! TL_GET( preemption_state ).enabled );265 verify( ! kernelTLS.preemption_state.enabled ); 252 266 unlock( *lock ); 253 267 } … … 256 270 } 257 271 else if( action_code == Release_Schedule ) { 258 verify( ! TL_GET( preemption_state ).enabled );272 verify( ! kernelTLS.preemption_state.enabled ); 259 273 unlock( *lock ); 260 274 ScheduleThread( thrd ); 261 275 } 262 276 else if( action_code == Release_Multi ) { 263 verify( ! TL_GET( preemption_state ).enabled );277 verify( ! kernelTLS.preemption_state.enabled ); 264 278 for(int i = 0; i < lock_count; i++) { 265 279 unlock( *locks[i] ); … … 285 299 } 286 300 301 // KERNEL_ONLY 287 302 // Context invoker for processors 288 303 // This is the entry point for processors (kernel threads) … … 290 305 void * CtxInvokeProcessor(void * arg) { 291 306 processor * proc = (processor *) arg; 292 TL_SET( this_processor, proc );293 TL_SET( this_coroutine, NULL );294 TL_SET( this_thread, NULL );295 TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];307 kernelTLS.this_processor = proc; 308 kernelTLS.this_coroutine = NULL; 309 kernelTLS.this_thread = NULL; 310 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1]; 296 311 // SKULLDUGGERY: We want to create a context for the processor coroutine 297 312 // which is needed for the 2-step context switch. However, there is no reason … … 305 320 306 321 //Set global state 307 TL_SET( this_coroutine, get_coroutine(proc->runner));308 TL_SET( this_thread, NULL );322 kernelTLS.this_coroutine = get_coroutine(proc->runner); 323 kernelTLS.this_thread = NULL; 309 324 310 325 //We now have a proper context from which to schedule threads … … 333 348 } 334 349 350 // KERNEL_ONLY 335 351 void kernel_first_resume(processor * this) { 336 coroutine_desc * src = TL_GET( this_coroutine );352 coroutine_desc * src = kernelTLS.this_coroutine; 337 353 coroutine_desc * dst = get_coroutine(this->runner); 338 354 339 verify( ! TL_GET( preemption_state ).enabled );355 verify( ! kernelTLS.preemption_state.enabled ); 340 356 341 357 create_stack(&dst->stack, dst->stack.size); 342 358 CtxStart(&this->runner, CtxInvokeCoroutine); 343 359 344 verify( ! TL_GET( preemption_state ).enabled );360 verify( ! kernelTLS.preemption_state.enabled ); 345 361 346 362 dst->last = src; … … 351 367 352 368 // set new coroutine that task is executing 353 TL_SET( this_coroutine, dst );369 kernelTLS.this_coroutine = dst; 354 370 355 371 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. … … 368 384 src->state = Active; 369 385 370 verify( ! TL_GET( preemption_state ).enabled );386 verify( ! kernelTLS.preemption_state.enabled ); 371 387 } 372 388 373 389 //----------------------------------------------------------------------------- 374 390 // Scheduler routines 391 392 // KERNEL ONLY 375 393 void ScheduleThread( thread_desc * thrd ) { 376 // if( ! thrd ) return;377 394 verify( thrd ); 378 395 verify( thrd->self_cor.state != Halted ); 379 396 380 verify( ! TL_GET( preemption_state ).enabled );397 verify( ! kernelTLS.preemption_state.enabled ); 381 398 382 399 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); … … 388 405 } 389 406 390 verify( ! TL_GET( preemption_state ).enabled ); 391 } 392 407 verify( ! kernelTLS.preemption_state.enabled ); 408 } 409 410 // KERNEL ONLY 393 411 thread_desc * nextThread(cluster * this) with( *this ) { 394 verify( ! TL_GET( preemption_state ).enabled );412 verify( ! kernelTLS.preemption_state.enabled ); 395 413 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 396 414 thread_desc * head = pop_head( ready_queue ); 397 415 unlock( ready_queue_lock ); 398 verify( ! TL_GET( preemption_state ).enabled );416 verify( ! kernelTLS.preemption_state.enabled ); 399 417 return head; 400 418 } … … 402 420 void BlockInternal() { 403 421 disable_interrupts(); 404 verify( ! TL_GET( preemption_state ).enabled );422 verify( ! kernelTLS.preemption_state.enabled ); 405 423 returnToKernel(); 406 verify( ! TL_GET( preemption_state ).enabled );424 verify( ! kernelTLS.preemption_state.enabled ); 407 425 enable_interrupts( __cfaabi_dbg_ctx ); 408 426 } … … 410 428 void BlockInternal( __spinlock_t * lock ) { 411 429 disable_interrupts(); 412 with( * TL_GET( this_processor )) {430 with( *kernelTLS.this_processor ) { 413 431 finish.action_code = Release; 414 432 finish.lock = lock; 415 433 } 416 434 417 verify( ! TL_GET( preemption_state ).enabled );435 verify( ! kernelTLS.preemption_state.enabled ); 418 436 returnToKernel(); 419 verify( ! TL_GET( preemption_state ).enabled );437 verify( ! kernelTLS.preemption_state.enabled ); 420 438 421 439 enable_interrupts( __cfaabi_dbg_ctx ); … … 424 442 void BlockInternal( thread_desc * thrd ) { 425 443 disable_interrupts(); 426 with( * TL_GET( this_processor )) {444 with( * kernelTLS.this_processor ) { 427 445 finish.action_code = Schedule; 428 446 finish.thrd = thrd; 429 447 } 430 448 431 verify( ! TL_GET( preemption_state ).enabled );449 verify( ! kernelTLS.preemption_state.enabled ); 432 450 returnToKernel(); 433 verify( ! TL_GET( preemption_state ).enabled );451 verify( ! kernelTLS.preemption_state.enabled ); 434 452 435 453 enable_interrupts( __cfaabi_dbg_ctx ); … … 439 457 assert(thrd); 440 458 disable_interrupts(); 441 with( * TL_GET( this_processor )) {459 with( * kernelTLS.this_processor ) { 442 460 finish.action_code = Release_Schedule; 443 461 finish.lock = lock; … … 445 463 } 446 464 447 verify( ! TL_GET( preemption_state ).enabled );465 verify( ! kernelTLS.preemption_state.enabled ); 448 466 returnToKernel(); 449 verify( ! TL_GET( preemption_state ).enabled );467 verify( ! kernelTLS.preemption_state.enabled ); 450 468 451 469 enable_interrupts( __cfaabi_dbg_ctx ); … … 454 472 void BlockInternal(__spinlock_t * locks [], unsigned short count) { 455 473 disable_interrupts(); 456 with( * TL_GET( this_processor )) {474 with( * kernelTLS.this_processor ) { 457 475 finish.action_code = Release_Multi; 458 476 finish.locks = locks; … … 460 478 } 461 479 462 verify( ! TL_GET( preemption_state ).enabled );480 verify( ! kernelTLS.preemption_state.enabled ); 463 481 returnToKernel(); 464 verify( ! TL_GET( preemption_state ).enabled );482 verify( ! kernelTLS.preemption_state.enabled ); 465 483 466 484 enable_interrupts( __cfaabi_dbg_ctx ); … … 469 487 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 470 488 disable_interrupts(); 471 with( * TL_GET( this_processor )) {489 with( *kernelTLS.this_processor ) { 472 490 finish.action_code = Release_Multi_Schedule; 473 491 finish.locks = locks; … … 477 495 } 478 496 479 verify( ! TL_GET( preemption_state ).enabled );497 verify( ! kernelTLS.preemption_state.enabled ); 480 498 returnToKernel(); 481 verify( ! TL_GET( preemption_state ).enabled );499 verify( ! kernelTLS.preemption_state.enabled ); 482 500 483 501 enable_interrupts( __cfaabi_dbg_ctx ); 484 502 } 485 503 504 // KERNEL ONLY 486 505 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 487 verify( ! TL_GET( preemption_state ).enabled );488 with( * TL_GET( this_processor )) {506 verify( ! kernelTLS.preemption_state.enabled ); 507 with( * kernelTLS.this_processor ) { 489 508 finish.action_code = thrd ? Release_Schedule : Release; 490 509 finish.lock = lock; … … 501 520 // Kernel boot procedures 502 521 void kernel_startup(void) { 503 verify( ! TL_GET( preemption_state ).enabled );522 verify( ! kernelTLS.preemption_state.enabled ); 504 523 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 524 525 global_threads. list{ __get }; 526 global_threads. lock{}; 527 global_clusters.list{ __get }; 528 global_clusters.lock{}; 505 529 506 530 // Initialize the main cluster … … 547 571 548 572 //initialize the global state variables 549 TL_SET( this_processor, mainProcessor );550 TL_SET( this_thread, mainThread );551 TL_SET( this_coroutine, &mainThread->self_cor );573 kernelTLS.this_processor = mainProcessor; 574 kernelTLS.this_thread = mainThread; 575 kernelTLS.this_coroutine = &mainThread->self_cor; 552 576 553 577 // Enable preemption … … 561 585 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 562 586 // mainThread is on the ready queue when this call is made. 563 kernel_first_resume( TL_GET( this_processor ));587 kernel_first_resume( kernelTLS.this_processor ); 564 588 565 589 … … 568 592 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 569 593 570 verify( ! TL_GET( preemption_state ).enabled );594 verify( ! kernelTLS.preemption_state.enabled ); 571 595 enable_interrupts( __cfaabi_dbg_ctx ); 572 verify( TL_GET( preemption_state ).enabled);596 verify( TL_GET( preemption_state.enabled ) ); 573 597 } 574 598 … … 576 600 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 577 601 578 verify( TL_GET( preemption_state ).enabled);602 verify( TL_GET( preemption_state.enabled ) ); 579 603 disable_interrupts(); 580 verify( ! TL_GET( preemption_state ).enabled );604 verify( ! kernelTLS.preemption_state.enabled ); 581 605 582 606 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 604 628 605 629 //============================================================================================= 630 // Kernel Quiescing 631 //============================================================================================= 632 633 // void halt(processor * this) with( this ) { 634 // pthread_mutex_lock( &idle.lock ); 635 636 637 638 // // SKULLDUGGERY: Even if spurious wake-up is a thing 639 // // spuriously waking up a kernel thread is not a big deal 640 // // if it is very rare. 641 // pthread_cond_wait( &idle.cond, &idle.lock); 642 // pthread_mutex_unlock( &idle.lock ); 643 // } 644 645 // void wake(processor * this) with( this ) { 646 // pthread_mutex_lock (&idle.lock); 647 // pthread_cond_signal (&idle.cond); 648 // pthread_mutex_unlock(&idle.lock); 649 // } 650 651 //============================================================================================= 606 652 // Unexpected Terminating logic 607 653 //============================================================================================= … … 609 655 610 656 static __spinlock_t kernel_abort_lock; 611 static __spinlock_t kernel_debug_lock;612 657 static bool kernel_abort_called = false; 613 658 614 void * kernel_abort 659 void * kernel_abort(void) __attribute__ ((__nothrow__)) { 615 660 // abort cannot be recursively entered by the same or different processors because all signal handlers return when 616 661 // the globalAbort flag is true. … … 618 663 619 664 // first task to abort ? 620 if ( ! kernel_abort_called ) { // not first task to abort ? 665 if ( kernel_abort_called ) { // not first task to abort ? 666 unlock( kernel_abort_lock ); 667 668 sigset_t mask; 669 sigemptyset( &mask ); 670 sigaddset( &mask, SIGALRM ); // block SIGALRM signals 671 sigsuspend( &mask ); // block the processor to prevent further damage during abort 672 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 673 } 674 else { 621 675 kernel_abort_called = true; 622 676 unlock( kernel_abort_lock ); 623 677 } 624 else { 625 unlock( kernel_abort_lock ); 626 627 sigset_t mask; 628 sigemptyset( &mask ); 629 sigaddset( &mask, SIGALRM ); // block SIGALRM signals 630 sigaddset( &mask, SIGUSR1 ); // block SIGUSR1 signals 631 sigsuspend( &mask ); // block the processor to prevent further damage during abort 632 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 633 } 634 635 return TL_GET( this_thread ); 678 679 return kernelTLS.this_thread; 636 680 } 637 681 … … 639 683 thread_desc * thrd = kernel_data; 640 684 641 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd->self_cor.name, thrd ); 642 __cfaabi_dbg_bits_write( abort_text, len ); 643 644 if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) { 645 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) ); 685 if(thrd) { 686 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd ); 646 687 __cfaabi_dbg_bits_write( abort_text, len ); 688 689 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) { 690 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine ); 691 __cfaabi_dbg_bits_write( abort_text, len ); 692 } 693 else { 694 __cfaabi_dbg_bits_write( ".\n", 2 ); 695 } 647 696 } 648 697 else { 649 __cfaabi_dbg_bits_write( ".\n", 2);698 int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" ); 650 699 } 651 700 } 652 701 653 702 int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) { 654 return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2; 655 } 703 return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2; 704 } 705 706 static __spinlock_t kernel_debug_lock; 656 707 657 708 extern "C" { … … 682 733 if ( count < 0 ) { 683 734 // queue current task 684 append( waiting, (thread_desc *)TL_GET( this_thread ));735 append( waiting, kernelTLS.this_thread ); 685 736 686 737 // atomically release spin lock and block … … 708 759 709 760 //----------------------------------------------------------------------------- 761 // Global Queues 762 void doregister( thread_desc & thrd ) { 763 // lock ( global_thread.lock ); 764 // push_front( global_thread.list, thrd ); 765 // unlock ( global_thread.lock ); 766 } 767 768 void unregister( thread_desc & thrd ) { 769 // lock ( global_thread.lock ); 770 // remove( global_thread.list, thrd ); 771 // unlock( global_thread.lock ); 772 } 773 774 void doregister( cluster & cltr ) { 775 // lock ( global_cluster.lock ); 776 // push_front( global_cluster.list, cltr ); 777 // unlock ( global_cluster.lock ); 778 } 779 780 void unregister( cluster & cltr ) { 781 // lock ( global_cluster.lock ); 782 // remove( global_cluster.list, cltr ); 783 // unlock( global_cluster.lock ); 784 } 785 786 787 void doregister( cluster * cltr, processor * proc ) { 788 // lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 789 // push_front(cltr->procs, *proc); 790 // unlock (cltr->proc_list_lock); 791 } 792 793 void unregister( cluster * cltr, processor * proc ) { 794 // lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 795 // remove(cltr->procs, *proc ); 796 // unlock(cltr->proc_list_lock); 797 } 798 799 //----------------------------------------------------------------------------- 710 800 // Debug 711 801 __cfaabi_dbg_debug_do( 712 struct {713 thread_desc * tail;714 } __cfaabi_dbg_thread_list = { NULL };715 716 void __cfaabi_dbg_thread_register( thread_desc * thrd ) {717 if( !__cfaabi_dbg_thread_list.tail ) {718 __cfaabi_dbg_thread_list.tail = thrd;719 return;720 }721 __cfaabi_dbg_thread_list.tail->dbg_next = thrd;722 thrd->dbg_prev = __cfaabi_dbg_thread_list.tail;723 __cfaabi_dbg_thread_list.tail = thrd;724 }725 726 void __cfaabi_dbg_thread_unregister( thread_desc * thrd ) {727 thread_desc * prev = thrd->dbg_prev;728 thread_desc * next = thrd->dbg_next;729 730 if( next ) { next->dbg_prev = prev; }731 else {732 assert( __cfaabi_dbg_thread_list.tail == thrd );733 __cfaabi_dbg_thread_list.tail = prev;734 }735 736 if( prev ) { prev->dbg_next = next; }737 738 thrd->dbg_prev = NULL;739 thrd->dbg_next = NULL;740 }741 742 802 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) { 743 803 this.prev_name = prev_name; 744 this.prev_thrd = TL_GET( this_thread );804 this.prev_thrd = kernelTLS.this_thread; 745 805 } 746 806 ) -
src/libcfa/concurrency/kernel_private.h
r7d0a3ba r358cba0 100 100 #define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)] 101 101 102 103 void doregister( struct thread_desc & thrd ); 104 void unregister( struct thread_desc & thrd ); 105 106 void doregister( struct cluster & cltr ); 107 void unregister( struct cluster & cltr ); 108 109 void doregister( struct cluster * cltr, struct processor * proc ); 110 void unregister( struct cluster * cltr, struct processor * proc ); 111 102 112 // Local Variables: // 103 113 // mode: c // -
src/libcfa/concurrency/monitor.c
r7d0a3ba r358cba0 85 85 // Lock the monitor spinlock 86 86 lock( this->lock __cfaabi_dbg_ctx2 ); 87 thread_desc * thrd = TL_GET( this_thread ); 87 // Interrupts disable inside critical section 88 thread_desc * thrd = kernelTLS.this_thread; 88 89 89 90 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); … … 134 135 // Lock the monitor spinlock 135 136 lock( this->lock __cfaabi_dbg_ctx2 ); 136 thread_desc * thrd = TL_GET( this_thread ); 137 // Interrupts disable inside critical section 138 thread_desc * thrd = kernelTLS.this_thread; 137 139 138 140 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); … … 168 170 169 171 // Create the node specific to this wait operation 170 wait_ctx_primed( TL_GET( this_thread ), 0 )172 wait_ctx_primed( thrd, 0 ) 171 173 172 174 // Some one else has the monitor, wait for him to finish and then run … … 179 181 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 180 182 181 wait_ctx( TL_GET( this_thread ), 0 )183 wait_ctx( thrd, 0 ) 182 184 this->dtor_node = &waiter; 183 185 … … 199 201 lock( this->lock __cfaabi_dbg_ctx2 ); 200 202 201 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", TL_GET( this_thread ), this, this->owner);202 203 verifyf( TL_GET( this_thread ) == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", TL_GET( this_thread ), this->owner, this->recursion, this );203 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner); 204 205 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 204 206 205 207 // Leaving a recursion level, decrement the counter … … 289 291 // Sorts monitors before entering 290 292 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) { 293 thread_desc * thrd = TL_GET( this_thread ); 294 291 295 // Store current array 292 296 this.m = m; … … 297 301 298 302 // Save previous thread context 299 this.prev = TL_GET( this_thread )->monitors;303 this.prev = thrd->monitors; 300 304 301 305 // Update thread context (needed for conditions) 302 ( TL_GET( this_thread )->monitors){m, count, func};306 (thrd->monitors){m, count, func}; 303 307 304 308 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count); … … 328 332 // Sorts monitors before entering 329 333 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) { 334 // optimization 335 thread_desc * thrd = TL_GET( this_thread ); 336 330 337 // Store current array 331 338 this.m = *m; 332 339 333 340 // Save previous thread context 334 this.prev = TL_GET( this_thread )->monitors;341 this.prev = thrd->monitors; 335 342 336 343 // Update thread context (needed for conditions) 337 ( TL_GET( this_thread )->monitors){m, 1, func};344 (thrd->monitors){m, 1, func}; 338 345 339 346 __enter_monitor_dtor( this.m, func ); … … 473 480 474 481 // Create the node specific to this wait operation 475 wait_ctx_primed( TL_GET( this_thread ), 0 )482 wait_ctx_primed( kernelTLS.this_thread, 0 ) 476 483 477 484 //save contexts … … 566 573 567 574 // Create the node specific to this wait operation 568 wait_ctx_primed( TL_GET( this_thread ), 0 );575 wait_ctx_primed( kernelTLS.this_thread, 0 ); 569 576 570 577 // Save monitor states … … 612 619 613 620 // Create the node specific to this wait operation 614 wait_ctx_primed( TL_GET( this_thread ), 0 );621 wait_ctx_primed( kernelTLS.this_thread, 0 ); 615 622 616 623 monitor_save; … … 618 625 619 626 for( __lock_size_t i = 0; i < count; i++) { 620 verify( monitors[i]->owner == TL_GET( this_thread ));627 verify( monitors[i]->owner == kernelTLS.this_thread ); 621 628 } 622 629 -
src/libcfa/concurrency/preemption.c
r7d0a3ba r358cba0 149 149 // Disable interrupts by incrementing the counter 150 150 void disable_interrupts() { 151 with( TL_GET( preemption_state )) {151 with( kernelTLS.preemption_state ) { 152 152 enabled = false; 153 153 __attribute__((unused)) unsigned short new_val = disable_count + 1; … … 160 160 // If counter reaches 0, execute any pending CtxSwitch 161 161 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 162 processor * proc = TL_GET( this_processor ); // Cache the processor now since interrupts can start happening after the atomic add163 thread_desc * thrd = TL_GET( this_thread ); // Cache the thread now since interrupts can start happening after the atomic add164 165 with( TL_GET( preemption_state )){162 processor * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic add 163 thread_desc * thrd = kernelTLS.this_thread; // Cache the thread now since interrupts can start happening after the atomic add 164 165 with( kernelTLS.preemption_state ){ 166 166 unsigned short prev = disable_count; 167 167 disable_count -= 1; … … 185 185 // Don't execute any pending CtxSwitch even if counter reaches 0 186 186 void enable_interrupts_noPoll() { 187 unsigned short prev = TL_GET( preemption_state ).disable_count;188 TL_GET( preemption_state ).disable_count -= 1;187 unsigned short prev = kernelTLS.preemption_state.disable_count; 188 kernelTLS.preemption_state.disable_count -= 1; 189 189 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 190 190 if( prev == 1 ) { 191 TL_GET( preemption_state ).enabled = true;191 kernelTLS.preemption_state.enabled = true; 192 192 } 193 193 } … … 234 234 } 235 235 236 236 // KERNEL ONLY 237 237 // Check if a CtxSwitch signal handler shoud defer 238 238 // If true : preemption is safe 239 239 // If false : preemption is unsafe and marked as pending 240 240 static inline bool preemption_ready() { 241 bool ready = TL_GET( preemption_state ).enabled && !TL_GET( preemption_state ).in_progress; // Check if preemption is safe 242 TL_GET( this_processor )->pending_preemption = !ready; // Adjust the pending flag accordingly 241 // Check if preemption is safe 242 bool ready = kernelTLS.preemption_state.enabled && ! kernelTLS.preemption_state.in_progress; 243 244 // Adjust the pending flag accordingly 245 kernelTLS.this_processor->pending_preemption = !ready; 243 246 return ready; 244 247 } … … 254 257 255 258 // Start with preemption disabled until ready 256 TL_GET( preemption_state ).enabled = false;257 TL_GET( preemption_state ).disable_count = 1;259 kernelTLS.preemption_state.enabled = false; 260 kernelTLS.preemption_state.disable_count = 1; 258 261 259 262 // Initialize the event kernel … … 320 323 // before the kernel thread has even started running. When that happens an iterrupt 321 324 // we a null 'this_processor' will be caught, just ignore it. 322 if(! TL_GET( this_processor )) return;325 if(! kernelTLS.this_processor ) return; 323 326 324 327 choose(sfp->si_value.sival_int) { 325 328 case PREEMPT_NORMAL : ;// Normal case, nothing to do here 326 case PREEMPT_TERMINATE: verify( TL_GET( this_processor )->do_terminate);329 case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate); 327 330 default: 328 331 abort( "internal error, signal value is %d", sfp->si_value.sival_int ); … … 332 335 if( !preemption_ready() ) { return; } 333 336 334 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", TL_GET( this_processor ), TL_GET( this_thread ) ); 335 336 TL_GET( preemption_state ).in_progress = true; // Sync flag : prevent recursive calls to the signal handler 337 signal_unblock( SIGUSR1 ); // We are about to CtxSwitch out of the signal handler, let other handlers in 338 TL_GET( preemption_state ).in_progress = false; // Clear the in progress flag 337 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", kernelTLS.this_processor, kernelTLS.this_thread ); 338 339 // Sync flag : prevent recursive calls to the signal handler 340 kernelTLS.preemption_state.in_progress = true; 341 342 // We are about to CtxSwitch out of the signal handler, let other handlers in 343 signal_unblock( SIGUSR1 ); 344 345 // TODO: this should go in finish action 346 // Clear the in progress flag 347 kernelTLS.preemption_state.in_progress = false; 339 348 340 349 // Preemption can occur here 341 350 342 BlockInternal( (thread_desc*)TL_GET( this_thread )); // Do the actual CtxSwitch351 BlockInternal( kernelTLS.this_thread ); // Do the actual CtxSwitch 343 352 } 344 353 … … 348 357 // Block sigalrms to control when they arrive 349 358 sigset_t mask; 359 sigfillset(&mask); 360 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) { 361 abort( "internal error, pthread_sigmask" ); 362 } 363 350 364 sigemptyset( &mask ); 351 365 sigaddset( &mask, SIGALRM ); 352 353 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {354 abort( "internal error, pthread_sigmask" );355 }356 366 357 367 // Main loop … … 409 419 410 420 void __cfaabi_check_preemption() { 411 bool ready = TL_GET( preemption_state ).enabled;421 bool ready = kernelTLS.preemption_state.enabled; 412 422 if(!ready) { abort("Preemption should be ready"); } 413 423 -
src/libcfa/concurrency/thread.c
r7d0a3ba r358cba0 39 39 curr_cluster = &cl; 40 40 next = NULL; 41 __cfaabi_dbg_debug_do( 42 dbg_next = NULL; 43 dbg_prev = NULL; 44 __cfaabi_dbg_thread_register(&this); 45 ) 41 42 node.next = NULL; 43 node.prev = NULL; 44 doregister(this); 46 45 47 46 monitors{ &self_mon_p, 1, (fptr_t)0 }; … … 49 48 50 49 void ^?{}(thread_desc& this) with( this ) { 50 unregister(this); 51 51 ^self_cor{}; 52 52 } … … 81 81 disable_interrupts(); 82 82 create_stack(&thrd_c->stack, thrd_c->stack.size); 83 TL_SET( this_coroutine, thrd_c );83 kernelTLS.this_coroutine = thrd_c; 84 84 CtxStart(&this, CtxInvokeThread); 85 85 assert( thrd_c->last->stack.context ); … … 91 91 92 92 extern "C" { 93 // KERNEL ONLY 93 94 void __finish_creation(void) { 94 coroutine_desc* thrd_c = TL_GET( this_coroutine );95 coroutine_desc* thrd_c = kernelTLS.this_coroutine; 95 96 ThreadCtxSwitch( thrd_c, thrd_c->last ); 96 97 } … … 98 99 99 100 void yield( void ) { 100 verify( TL_GET( preemption_state ).enabled ); 101 // Safety note : This could cause some false positives due to preemption 102 verify( TL_GET( preemption_state.enabled ) ); 101 103 BlockInternal( TL_GET( this_thread ) ); 102 verify( TL_GET( preemption_state ).enabled ); 104 // Safety note : This could cause some false positives due to preemption 105 verify( TL_GET( preemption_state.enabled ) ); 103 106 } 104 107 … … 109 112 } 110 113 114 // KERNEL ONLY 111 115 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 112 116 // set state of current coroutine to inactive … … 116 120 // set new coroutine that the processor is executing 117 121 // and context switch to it 118 TL_SET( this_coroutine, dst );122 kernelTLS.this_coroutine = dst; 119 123 assert( src->stack.context ); 120 124 CtxSwitch( src->stack.context, dst->stack.context ); 121 TL_SET( this_coroutine, src );125 kernelTLS.this_coroutine = src; 122 126 123 127 // set state of new coroutine to active -
src/libcfa/interpose.c
r7d0a3ba r358cba0 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 1 15:05:35 2018 13 // Update Count : 83 14 // 15 16 #include <stdarg.h> 17 #include <stddef.h> 18 19 extern "C" { 20 #include <stdio.h> 21 #include <string.h> 22 #include <dlfcn.h> 23 #include <unistd.h> 12 // Last Modified On : Sat May 5 11:37:35 2018 13 // Update Count : 111 14 // 15 16 #include <stdarg.h> // va_start, va_end 17 #include <string.h> // strlen 18 #include <unistd.h> // _exit, getpid 24 19 #define __USE_GNU 25 20 #include <signal.h> 26 21 #undef __USE_GNU 27 #include <execinfo.h> 22 extern "C" { 23 #include <dlfcn.h> // dlopen, dlsym 24 #include <execinfo.h> // backtrace, messages 28 25 } 29 26 30 27 #include "bits/debug.h" 31 28 #include "bits/defs.h" 32 #include "bits/signal.h" 33 #include "startup.h" 29 #include "bits/signal.h" // sigHandler_? 30 #include "startup.h" // STARTUP_PRIORITY_CORE 34 31 35 32 //============================================================================================= … … 37 34 //============================================================================================= 38 35 39 typedef void (* generic_fptr_t)(void);40 generic_fptr_t interpose_symbol( const char * symbol, const char *version ) {36 typedef void (* generic_fptr_t)(void); 37 generic_fptr_t interpose_symbol( const char * symbol, const char * version ) { 41 38 const char * error; 42 39 … … 55 52 } // if 56 53 57 union { generic_fptr_t fptr; void * ptr; } originalFunc;54 union { generic_fptr_t fptr; void * ptr; } originalFunc; 58 55 59 56 #if defined( _GNU_SOURCE ) … … 73 70 } 74 71 75 forall(dtype T) 76 static inline void ptr_from_symbol( T** symbol_ptr, const char * symbol_name, const char * version) { 77 union { 78 generic_fptr_t gp; 79 T* tp; 80 } u; 81 82 u.gp = interpose_symbol( symbol_name, version ); 83 84 *symbol_ptr = u.tp; 85 } 86 87 #define INTERPOSE_LIBC( x, ver ) ptr_from_symbol( (void**)&__cabi_libc.x, #x, ver) 88 89 //============================================================================================= 90 // Terminating Signals logic 72 #define INTERPOSE_LIBC( x, ver ) __cabi_libc.x = (typeof(__cabi_libc.x))interpose_symbol( #x, ver ) 73 74 //============================================================================================= 75 // Interposition Startup logic 91 76 //============================================================================================= 92 77 … … 98 83 99 84 struct { 100 void (* exit)( int ) __attribute__ 101 void (* abort)( void ) __attribute__ 85 void (* exit)( int ) __attribute__(( __noreturn__ )); 86 void (* abort)( void ) __attribute__(( __noreturn__ )); 102 87 } __cabi_libc; 103 88 … … 107 92 const char *version = NULL; 108 93 94 #pragma GCC diagnostic push 95 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 109 96 INTERPOSE_LIBC( abort, version ); 110 97 INTERPOSE_LIBC( exit , version ); 111 112 __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); // Failure handler 113 __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); // Failure handler 114 __cfaabi_sigaction( SIGILL , sigHandler_ill , SA_SIGINFO ); // Failure handler 115 __cfaabi_sigaction( SIGFPE , sigHandler_fpe , SA_SIGINFO ); // Failure handler 116 __cfaabi_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO ); // Failure handler 117 __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO ); // Failure handler 118 __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO ); // Failure handler 98 #pragma GCC diagnostic pop 99 100 // Failure handler 101 __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); 102 __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); 103 __cfaabi_sigaction( SIGILL , sigHandler_ill , SA_SIGINFO ); 104 __cfaabi_sigaction( SIGFPE , sigHandler_fpe , SA_SIGINFO ); 105 __cfaabi_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO | SA_RESETHAND); 106 __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO ); 107 __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO ); 119 108 } 120 109 } … … 125 114 126 115 // Forward declare abort after the __typeof__ call to avoid ambiguities 127 void exit( int status, const char fmt[], ... ) __attribute__ 128 void abort( const char fmt[], ... ) __attribute__ 116 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 117 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 129 118 130 119 extern "C" { 131 void abort( void ) __attribute__ 120 void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) { 132 121 abort( NULL ); 133 122 } 134 123 135 void __cabi_abort( const char fmt[], ... ) __attribute__ 124 void __cabi_abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) { 136 125 va_list argp; 137 126 va_start( argp, fmt ); … … 140 129 } 141 130 142 void exit( int status ) __attribute__ 131 void exit( int status ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) { 143 132 __cabi_libc.exit( status ); 144 133 } 145 134 } 146 135 147 void * kernel_abort ( void ) __attribute__ 148 void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ 149 int kernel_abort_lastframe( void ) __attribute__ 136 void * kernel_abort ( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return NULL; } 137 void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {} 138 int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; } 150 139 151 140 enum { abort_text_size = 1024 }; … … 153 142 static int abort_lastframe; 154 143 155 void exit( int status, const char fmt[], ... ) __attribute__ 144 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) { 156 145 va_list args; 157 146 va_start( args, fmt ); … … 161 150 } 162 151 163 void abort( const char fmt[], ... ) __attribute__ 152 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) { 164 153 void * kernel_data = kernel_abort(); // must be done here to lock down kernel 165 154 int len; -
src/libcfa/stdlib
r7d0a3ba r358cba0 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jan 2 12:21:04201813 // Update Count : 29 212 // Last Modified On : Sun May 13 23:22:23 2018 13 // Update Count : 299 14 14 // 15 15 16 16 #pragma once 17 17 18 //#define _XOPEN_SOURCE 600 // posix_memalign, *rand48 18 #define __USE_ISOC11 // aligned_alloc 19 19 #include <stdlib.h> // strto*, *abs 20 20 … … 28 28 //--------------------------------------- 29 29 30 // allocation, non-array types 31 static inline forall( dtype T | sized(T) ) T * malloc( void ) { 32 // printf( "* malloc\n" ); 33 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 34 } // malloc 35 36 // static inline forall( dtype T | sized(T) ) T & malloc( void ) { 37 // int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 38 // printf( "& malloc %p\n", &p ); 39 // return p; 40 // // return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 41 // } // malloc 42 43 extern "C" { void * calloc( size_t dim, size_t size ); } // default C routine 44 static inline forall( dtype T | sized(T) ) T * calloc( size_t dim ) { 45 //printf( "X2\n" ); 46 return (T *)(void *)calloc( dim, sizeof(T) ); // C cmalloc 47 } 48 49 extern "C" { void * realloc( void * ptr, size_t size ); } // default C routine for void * 50 static inline forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size ) { 51 //printf( "X3\n" ); 52 return (T *)(void *)realloc( (void *)ptr, size ); 53 } 54 55 extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void * 56 static inline forall( dtype T | sized(T) ) T * memalign( size_t align ) { 57 //printf( "X4\n" ); 58 return (T *)memalign( align, sizeof(T) ); 59 } // memalign 60 61 static inline forall( dtype T | sized(T) ) T * aligned_alloc( size_t align ) { 62 //printf( "X5\n" ); 63 return (T *)memalign( align, sizeof(T) ); 64 } // aligned_alloc 65 66 extern "C" { int posix_memalign( void ** ptr, size_t align, size_t size ); } // use default C routine for void * 67 static inline forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t align ) { 68 //printf( "X6\n" ); 69 return posix_memalign( (void **)ptr, align, sizeof(T) ); 70 } // posix_memalign 71 72 73 extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void * 74 75 static inline forall( dtype T | sized(T) ) T * alloc( void ) { 76 //printf( "X7\n" ); 77 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 78 } // alloc 79 static inline forall( dtype T | sized(T) ) T * alloc( char fill ) { 80 //printf( "X8\n" ); 81 T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 82 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initial with fill value 83 } // alloc 84 85 static inline forall( dtype T | sized(T) ) T * alloc( size_t dim ) { 86 //printf( "X9\n" ); 87 return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc 88 } // alloc 89 static inline forall( dtype T | sized(T) ) T * alloc( size_t dim, char fill ) { 90 //printf( "X10\n" ); 91 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc 92 return (T *)memset( ptr, (int)fill, dim * sizeof(T) ); 93 } // alloc 94 95 static inline forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim ) { 96 //printf( "X11\n" ); 97 return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc 98 } // alloc 30 // C dynamic allocation 31 static inline forall( dtype T | sized(T) ) { 32 T * malloc( void ) { 33 // printf( "* malloc\n" ); 34 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 35 } // malloc 36 37 // T & malloc( void ) { 38 // int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 39 // printf( "& malloc %p\n", &p ); 40 // return p; 41 // // return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 42 // } // malloc 43 44 T * calloc( size_t dim ) { 45 //printf( "X2\n" ); 46 return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc 47 } // calloc 48 49 T * realloc( T * ptr, size_t size ) { 50 //printf( "X3\n" ); 51 return (T *)(void *)realloc( (void *)ptr, size ); 52 } // realloc 53 54 extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void * 55 T * memalign( size_t align ) { 56 //printf( "X4\n" ); 57 return (T *)memalign( align, sizeof(T) ); 58 } // memalign 59 60 extern "C" { void * aligned_alloc( size_t align, size_t size ); } // use default C routine for void * 61 T * aligned_alloc( size_t align ) { 62 //printf( "X5\n" ); 63 return (T *)aligned_alloc( align, sizeof(T) ); 64 } // aligned_alloc 65 66 int posix_memalign( T ** ptr, size_t align ) { 67 //printf( "X6\n" ); 68 return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign 69 } // posix_memalign 70 71 72 // Cforall dynamic allocation 73 extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void * 74 75 T * alloc( void ) { 76 //printf( "X7\n" ); 77 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 78 } // alloc 79 80 T * alloc( char fill ) { 81 //printf( "X8\n" ); 82 T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 83 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initial with fill value 84 } // alloc 85 86 T * alloc( size_t dim ) { 87 //printf( "X9\n" ); 88 return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc 89 } // alloc 90 91 T * alloc( size_t dim, char fill ) { 92 //printf( "X10\n" ); 93 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc 94 return (T *)memset( ptr, (int)fill, dim * sizeof(T) ); // initial with fill value 95 } // alloc 96 97 T * alloc( T ptr[], size_t dim ) { 98 //printf( "X11\n" ); 99 return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc 100 } // alloc 101 } // distribution 102 103 99 104 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill ); 100 105 -
src/libcfa/time.c
r7d0a3ba r358cba0 10 10 // Created On : Tue Mar 27 13:33:14 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 12 14:41:00 201813 // Update Count : 2212 // Last Modified On : Sun May 6 22:26:00 2018 13 // Update Count : 37 14 14 // 15 15 … … 17 17 #include "iostream" 18 18 #include <stdio.h> // snprintf 19 #include <assert.h> 19 20 20 21 static char * nanomsd( long int ns, char * buf ) { // most significant digits … … 87 88 time_t s = tv / TIMEGRAN; 88 89 tm tm; 89 gmtime_r( &s, &tm ); 90 gmtime_r( &s, &tm ); // tm_mon <= 11, tm_mday <= 31 91 #if defined(__GNUC__) && __GNUC__ >= 7 92 #pragma GCC diagnostic push 93 #pragma GCC diagnostic ignored "-Wformat-truncation" 94 #endif 90 95 snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_year % 99, tm.tm_mon + 1, tm.tm_mday ); 96 #if defined(__GNUC__) && __GNUC__ >= 7 97 #pragma GCC diagnostic pop 98 #endif 91 99 return buf; 92 100 } // yy_mm_dd … … 95 103 time_t s = tv / TIMEGRAN; 96 104 tm tm; 97 gmtime_r( &s, &tm ); 105 gmtime_r( &s, &tm ); // tm_mon <= 11, tm_mday <= 31 106 #if defined(__GNUC__) && __GNUC__ >= 7 107 #pragma GCC diagnostic push 108 #pragma GCC diagnostic ignored "-Wformat-truncation" 109 #endif 98 110 snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_year % 99 ); 111 #if defined(__GNUC__) && __GNUC__ >= 7 112 #pragma GCC diagnostic pop 113 #endif 99 114 return buf; 100 115 } // mm_dd_yy … … 103 118 time_t s = tv / TIMEGRAN; 104 119 tm tm; 105 gmtime_r( &s, &tm ); 120 gmtime_r( &s, &tm ); // tm_mon <= 11, tm_mday <= 31 121 #if defined(__GNUC__) && __GNUC__ >= 7 122 #pragma GCC diagnostic push 123 #pragma GCC diagnostic ignored "-Wformat-truncation" 124 #endif 106 125 snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 99 ); 126 #if defined(__GNUC__) && __GNUC__ >= 7 127 #pragma GCC diagnostic pop 128 #endif 107 129 return buf; 108 130 } // dd_mm_yy -
src/main.cc
r7d0a3ba r358cba0 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 2 14:59:02201813 // Update Count : 49 012 // Last Modified On : Mon May 7 14:35:57 2018 13 // Update Count : 492 14 14 // 15 15 … … 64 64 65 65 #define PASS(name, pass) \ 66 if ( errorp ) { cerr << #name << endl; } \67 HeapStats::newPass( #name); \66 if ( errorp ) { cerr << name << endl; } \ 67 HeapStats::newPass(name); \ 68 68 pass; 69 69 … … 371 371 } // if 372 372 return 1; 373 } // try 373 } catch(...) { 374 std::exception_ptr eptr = std::current_exception(); 375 try { 376 if (eptr) { 377 std::rethrow_exception(eptr); 378 } 379 else { 380 std::cerr << "Exception Uncaught and Unkown" << std::endl; 381 } 382 } catch(const std::exception& e) { 383 std::cerr << "Unaught Exception \"" << e.what() << "\"\n"; 384 } 385 return 1; 386 }// try 374 387 375 388 deleteAll( translationUnit ); 376 HeapStats::printStats();389 if(!libcfap && !treep) HeapStats::printStats(); 377 390 return 0; 378 391 } // main … … 407 420 opterr = 0; // (global) prevent getopt from printing error messages 408 421 409 bool W error = false;422 bool Wsuppress = false, Werror = false; 410 423 int c; 411 424 while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) { … … 495 508 break; 496 509 case 'w': 497 SemanticWarning_SuppressAll();510 Wsuppress = true; 498 511 break; 499 512 case 'W': … … 534 547 assertf( false, "Unknown option: %s\n", argv[optind - 1] ); 535 548 } // if 536 #if __GNUC__ < 7 537 #else 549 #if defined(__GNUC__) && __GNUC__ >= 7 538 550 __attribute__((fallthrough)); 539 551 #endif … … 545 557 if ( Werror ) { 546 558 SemanticWarning_WarningAsError(); 559 } // if 560 if ( Wsuppress ) { 561 SemanticWarning_SuppressAll(); 547 562 } // if 548 563 // for ( const auto w : WarningFormats ) { -
src/tests/coroutine/fmtLines.c
r7d0a3ba r358cba0 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // fmtLines.cc -- 7 // fmtLines.cc -- format characters into blocks of 4 and groups of 5 blocks per line 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sun Sep 17 21:56:15 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 5 21:56:35 201713 // Update Count : 3812 // Last Modified On : Tue May 15 12:25:33 2018 13 // Update Count : 42 14 14 // 15 15 … … 21 21 int g, b; // global because used in destructor 22 22 }; 23 24 void ?{}( Format & fmt ) {25 resume( fmt ); // prime (start) coroutine26 }27 28 void ^?{}( Format & fmt ) with( fmt ) {29 if ( g != 0 || b != 0 ) sout | endl;30 }31 23 32 24 void main( Format & fmt ) with( fmt ) { … … 46 38 } // main 47 39 48 void prt( Format & fmt, char ch ) { 49 fmt.ch = ch; 40 void ?{}( Format & fmt ) { 41 resume( fmt ); // prime (start) coroutine 42 } 43 44 void ^?{}( Format & fmt ) with( fmt ) { 45 if ( g != 0 || b != 0 ) sout | endl; 46 } 47 48 void format( Format & fmt ) { 50 49 resume( fmt ); 51 50 } // prt 52 51 53 52 int main() { 54 Format fmt; // format characters into blocks of 4 and groups of 5 blocks per line 55 char ch; 53 Format fmt; 56 54 57 Eof: for ( ;; ) { // read until end of file58 sin | ch;// read one character59 if ( eof( sin ) ) break Eof; // eof ?60 prt( fmt, ch); // push character for formatting55 eof: for ( ;; ) { // read until end of file 56 sin | fmt.ch; // read one character 57 if ( eof( sin ) ) break eof; // eof ? 58 format( fmt ); // push character for formatting 61 59 } // for 62 60 } // main
Note: See TracChangeset
for help on using the changeset viewer.