Changes in / [a2e4b0c:a51a02d]


Ignore:
Files:
1 added
4 deleted
31 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/mubeen_zulfiqar_MMath/allocator.tex

    ra2e4b0c ra51a02d  
    2424\end{itemize}
    2525
    26 The new features added to uHeapLmmm (incl. @malloc\_size@ routine)
     26The new features added to uHeapLmmm (incl. @malloc_size@ routine)
    2727\CFA alloc interface with examples.
    28 
    2928\begin{itemize}
    3029\item
     
    118117We added a few more features and routines to the allocator's C interface that can make the allocator more usable to the programmers. THese features will programmer more control on the dynamic memory allocation.
    119118
    120 \subsubsection void * aalloc( size\_t dim, size\_t elemSize )
     119\subsubsection void * aalloc( size_t dim, size_t elemSize )
    121120aalloc is an extension of malloc. It allows programmer to allocate a dynamic array of objects without calculating the total size of array explicitly. The only alternate of this routine in the other allocators is calloc but calloc also fills the dynamic memory with 0 which makes it slower for a programmer who only wants to dynamically allocate an array of objects without filling it with 0.
    122121\paragraph{Usage}
    123122aalloc takes two parameters.
    124 
    125123\begin{itemize}
    126124\item
     
    131129It returns address of dynamic object allocatoed on heap that can contain dim number of objects of the size elemSize. On failure, it returns NULL pointer.
    132130
    133 \subsubsection void * resize( void * oaddr, size\_t size )
     131\subsubsection void * resize( void * oaddr, size_t size )
    134132resize is an extension of relloc. It allows programmer to reuse a cuurently allocated dynamic object with a new size requirement. Its alternate in the other allocators is realloc but relloc also copy the data in old object to the new object which makes it slower for the programmer who only wants to reuse an old dynamic object for a new size requirement but does not want to preserve the data in the old object to the new object.
    135133\paragraph{Usage}
    136134resize takes two parameters.
    137 
    138135\begin{itemize}
    139136\item
     
    144141It returns an object that is of the size given but it does not preserve the data in the old object. On failure, it returns NULL pointer.
    145142
    146 \subsubsection void * resize( void * oaddr, size\_t nalign, size\_t size )
     143\subsubsection void * resize( void * oaddr, size_t nalign, size_t size )
    147144This resize is an extension of the above resize (FIX ME: cite above resize). In addition to resizing the size of of an old object, it can also realign the old object to a new alignment requirement.
    148145\paragraph{Usage}
    149146This resize takes three parameters. It takes an additional parameter of nalign as compared to the above resize (FIX ME: cite above resize).
    150 
    151147\begin{itemize}
    152148\item
     
    159155It returns an object with the size and alignment given in the parameters. On failure, it returns a NULL pointer.
    160156
    161 \subsubsection void * amemalign( size\_t alignment, size\_t dim, size\_t elemSize )
     157\subsubsection void * amemalign( size_t alignment, size_t dim, size_t elemSize )
    162158amemalign is a hybrid of memalign and aalloc. It allows programmer to allocate an aligned dynamic array of objects without calculating the total size of the array explicitly. It frees the programmer from calculating the total size of the array.
    163159\paragraph{Usage}
    164160amemalign takes three parameters.
    165 
    166161\begin{itemize}
    167162\item
     
    174169It returns a dynamic array of objects that has the capacity to contain dim number of objects of the size of elemSize. The returned dynamic array is aligned to the given alignment. On failure, it returns NULL pointer.
    175170
    176 \subsubsection void * cmemalign( size\_t alignment, size\_t dim, size\_t elemSize )
     171\subsubsection void * cmemalign( size_t alignment, size_t dim, size_t elemSize )
    177172cmemalign is a hybrid of amemalign and calloc. It allows programmer to allocate an aligned dynamic array of objects that is 0 filled. The current way to do this in other allocators is to allocate an aligned object with memalign and then fill it with 0 explicitly. This routine provides both features of aligning and 0 filling, implicitly.
    178173\paragraph{Usage}
    179174cmemalign takes three parameters.
    180 
    181175\begin{itemize}
    182176\item
     
    189183It returns a dynamic array of objects that has the capacity to contain dim number of objects of the size of elemSize. The returned dynamic array is aligned to the given alignment and is 0 filled. On failure, it returns NULL pointer.
    190184
    191 \subsubsection size\_t malloc\_alignment( void * addr )
    192 malloc\_alignment returns the alignment of a currently allocated dynamic object. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verofying the alignment of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was allocated with the required alignment.
    193 \paragraph{Usage}
    194 malloc\_alignment takes one parameters.
    195 
     185\subsubsection size_t malloc_alignment( void * addr )
     186malloc_alignment returns the alignment of a currently allocated dynamic object. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verofying the alignment of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was allocated with the required alignment.
     187\paragraph{Usage}
     188malloc_alignment takes one parameters.
    196189\begin{itemize}
    197190\item
    198191addr: the address of the currently allocated dynamic object.
    199192\end{itemize}
    200 malloc\_alignment returns the alignment of the given dynamic object. On failure, it return the value of default alignment of the uHeapLmmm allocator.
    201 
    202 \subsubsection bool malloc\_zero\_fill( void * addr )
    203 malloc\_zero\_fill returns whether a currently allocated dynamic object was initially zero filled at the time of allocation. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verifying the zero filled property of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was zero filled at the time of allocation.
    204 \paragraph{Usage}
    205 malloc\_zero\_fill takes one parameters.
    206 
     193malloc_alignment returns the alignment of the given dynamic object. On failure, it return the value of default alignment of the uHeapLmmm allocator.
     194
     195\subsubsection bool malloc_zero_fill( void * addr )
     196malloc_zero_fill returns whether a currently allocated dynamic object was initially zero filled at the time of allocation. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verifying the zero filled property of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was zero filled at the time of allocation.
     197\paragraph{Usage}
     198malloc_zero_fill takes one parameters.
    207199\begin{itemize}
    208200\item
    209201addr: the address of the currently allocated dynamic object.
    210202\end{itemize}
    211 malloc\_zero\_fill returns true if the dynamic object was initially zero filled and return false otherwise. On failure, it returns false.
    212 
    213 \subsubsection size\_t malloc\_size( void * addr )
    214 malloc\_size returns the allocation size of a currently allocated dynamic object. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verofying the alignment of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was allocated with the required size. Its current alternate in the other allocators is malloc\_usable\_size. But, malloc\_size is different from malloc\_usable\_size as malloc\_usabe\_size returns the total data capacity of dynamic object including the extra space at the end of the dynamic object. On the other hand, malloc\_size returns the size that was given to the allocator at the allocation of the dynamic object. This size is updated when an object is realloced, resized, or passed through a similar allocator routine.
    215 \paragraph{Usage}
    216 malloc\_size takes one parameters.
    217 
     203malloc_zero_fill returns true if the dynamic object was initially zero filled and return false otherwise. On failure, it returns false.
     204
     205\subsubsection size_t malloc_size( void * addr )
     206malloc_size returns the allocation size of a currently allocated dynamic object. It allows the programmer in memory management and personal bookkeeping. It helps the programmer in verofying the alignment of a dynamic object especially in a scenerio similar to prudcer-consumer where a producer allocates a dynamic object and the consumer needs to assure that the dynamic object was allocated with the required size. Its current alternate in the other allocators is malloc_usable_size. But, malloc_size is different from malloc_usable_size as malloc_usabe_size returns the total data capacity of dynamic object including the extra space at the end of the dynamic object. On the other hand, malloc_size returns the size that was given to the allocator at the allocation of the dynamic object. This size is updated when an object is realloced, resized, or passed through a similar allocator routine.
     207\paragraph{Usage}
     208malloc_size takes one parameters.
    218209\begin{itemize}
    219210\item
    220211addr: the address of the currently allocated dynamic object.
    221212\end{itemize}
    222 malloc\_size returns the allocation size of the given dynamic object. On failure, it return zero.
    223 
    224 \subsubsection void * realloc( void * oaddr, size\_t nalign, size\_t size )
     213malloc_size returns the allocation size of the given dynamic object. On failure, it return zero.
     214
     215\subsubsection void * realloc( void * oaddr, size_t nalign, size_t size )
    225216This realloc is an extension of the default realloc (FIX ME: cite default realloc). In addition to reallocating an old object and preserving the data in old object, it can also realign the old object to a new alignment requirement.
    226217\paragraph{Usage}
    227218This realloc takes three parameters. It takes an additional parameter of nalign as compared to the default realloc.
    228 
    229219\begin{itemize}
    230220\item
     
    247237It returns a dynamic object of the size of type T. On failure, it return NULL pointer.
    248238
    249 \subsubsection T * aalloc( size\_t dim )
     239\subsubsection T * aalloc( size_t dim )
    250240This aalloc is a simplified polymorphic form of above aalloc (FIX ME: cite aalloc). It takes one parameter as compared to the above aalloc that takes two parameters.
    251241\paragraph{Usage}
    252242aalloc takes one parameters.
    253 
    254243\begin{itemize}
    255244\item
     
    258247It returns a dynamic object that has the capacity to contain dim number of objects, each of the size of type T. On failure, it return NULL pointer.
    259248
    260 \subsubsection T * calloc( size\_t dim )
     249\subsubsection T * calloc( size_t dim )
    261250This calloc is a simplified polymorphic form of defualt calloc (FIX ME: cite calloc). It takes one parameter as compared to the default calloc that takes two parameters.
    262251\paragraph{Usage}
    263252This calloc takes one parameter.
    264 
    265253\begin{itemize}
    266254\item
     
    269257It returns a dynamic object that has the capacity to contain dim number of objects, each of the size of type T. On failure, it return NULL pointer.
    270258
    271 \subsubsection T * resize( T * ptr, size\_t size )
     259\subsubsection T * resize( T * ptr, size_t size )
    272260This resize is a simplified polymorphic form of above resize (FIX ME: cite resize with alignment). It takes two parameters as compared to the above resize that takes three parameters. It frees the programmer from explicitly mentioning the alignment of the allocation as CFA provides gives allocator the liberty to get the alignment of the returned type.
    273261\paragraph{Usage}
    274262This resize takes two parameters.
    275 
    276263\begin{itemize}
    277264\item
     
    282269It returns a dynamic object of the size given in paramters. The returned object is aligned to the alignemtn of type T. On failure, it return NULL pointer.
    283270
    284 \subsubsection T * realloc( T * ptr, size\_t size )
     271\subsubsection T * realloc( T * ptr, size_t size )
    285272This realloc is a simplified polymorphic form of defualt realloc (FIX ME: cite realloc with align). It takes two parameters as compared to the above realloc that takes three parameters. It frees the programmer from explicitly mentioning the alignment of the allocation as CFA provides gives allocator the liberty to get the alignment of the returned type.
    286273\paragraph{Usage}
    287274This realloc takes two parameters.
    288 
    289275\begin{itemize}
    290276\item
     
    295281It returns a dynamic object of the size given in paramters that preserves the data in the given object. The returned object is aligned to the alignemtn of type T. On failure, it return NULL pointer.
    296282
    297 \subsubsection T * memalign( size\_t align )
     283\subsubsection T * memalign( size_t align )
    298284This memalign is a simplified polymorphic form of defualt memalign (FIX ME: cite memalign). It takes one parameters as compared to the default memalign that takes two parameters.
    299285\paragraph{Usage}
    300286memalign takes one parameters.
    301 
    302287\begin{itemize}
    303288\item
     
    306291It returns a dynamic object of the size of type T that is aligned to given parameter align. On failure, it return NULL pointer.
    307292
    308 \subsubsection T * amemalign( size\_t align, size\_t dim )
     293\subsubsection T * amemalign( size_t align, size_t dim )
    309294This amemalign is a simplified polymorphic form of above amemalign (FIX ME: cite amemalign). It takes two parameter as compared to the above amemalign that takes three parameters.
    310295\paragraph{Usage}
    311296amemalign takes two parameters.
    312 
    313297\begin{itemize}
    314298\item
     
    319303It returns a dynamic object that has the capacity to contain dim number of objects, each of the size of type T. The returned object is aligned to the given parameter align. On failure, it return NULL pointer.
    320304
    321 \subsubsection T * cmemalign( size\_t align, size\_t dim  )
     305\subsubsection T * cmemalign( size_t align, size_t dim  )
    322306This cmemalign is a simplified polymorphic form of above cmemalign (FIX ME: cite cmemalign). It takes two parameter as compared to the above cmemalign that takes three parameters.
    323307\paragraph{Usage}
    324308cmemalign takes two parameters.
    325 
    326309\begin{itemize}
    327310\item
     
    332315It returns a dynamic object that has the capacity to contain dim number of objects, each of the size of type T. The returned object is aligned to the given parameter align and is zero filled. On failure, it return NULL pointer.
    333316
    334 \subsubsection T * aligned\_alloc( size\_t align )
    335 This aligned\_alloc is a simplified polymorphic form of defualt aligned\_alloc (FIX ME: cite aligned\_alloc). It takes one parameter as compared to the default aligned\_alloc that takes two parameters.
    336 \paragraph{Usage}
    337 This aligned\_alloc takes one parameter.
    338 
     317\subsubsection T * aligned_alloc( size_t align )
     318This aligned_alloc is a simplified polymorphic form of defualt aligned_alloc (FIX ME: cite aligned_alloc). It takes one parameter as compared to the default aligned_alloc that takes two parameters.
     319\paragraph{Usage}
     320This aligned_alloc takes one parameter.
    339321\begin{itemize}
    340322\item
     
    343325It returns a dynamic object of the size of type T that is aligned to the given parameter. On failure, it return NULL pointer.
    344326
    345 \subsubsection int posix\_memalign( T ** ptr, size\_t align )
    346 This posix\_memalign is a simplified polymorphic form of defualt posix\_memalign (FIX ME: cite posix\_memalign). It takes two parameters as compared to the default posix\_memalign that takes three parameters.
    347 \paragraph{Usage}
    348 This posix\_memalign takes two parameter.
    349 
     327\subsubsection int posix_memalign( T ** ptr, size_t align )
     328This posix_memalign is a simplified polymorphic form of defualt posix_memalign (FIX ME: cite posix_memalign). It takes two parameters as compared to the default posix_memalign that takes three parameters.
     329\paragraph{Usage}
     330This posix_memalign takes two parameter.
    350331\begin{itemize}
    351332\item
     
    354335align: required alignment of the dynamic object.
    355336\end{itemize}
    356 
    357337It stores address of the dynamic object of the size of type T in given parameter ptr. This object is aligned to the given parameter. On failure, it return NULL pointer.
    358338
     
    369349It returns a dynamic object of the size that is calcutaed by rouding the size of type T. The returned object is also aligned to the page size. On failure, it return NULL pointer.
    370350
    371 \subsection Alloc Interface
     351\subsection{Alloc Interface}
    372352In addition to improve allocator interface both for CFA and our standalone allocator uHeapLmmm in C. We also added a new alloc interface in CFA that increases usability of dynamic memory allocation.
    373353This interface helps programmers in three major ways.
    374 
    375354\begin{itemize}
    376355\item
     
    392371This is the only parameter in the alloc routine that has a fixed-position and it is also the only parameter that does not use a backtick function. It has to be passed at the first position to alloc call in-case of an array allocation of objects of type T.
    393372It represents the required number of members in the array allocation as in CFA's aalloc (FIX ME: cite aalloc).
    394 This parameter should be of type size\_t.
     373This parameter should be of type size_t.
    395374
    396375Example: int a = alloc( 5 )
     
    398377
    399378\paragraph{Align}
    400 This parameter is position-free and uses a backtick routine align (`align). The parameter passed with `align should be of type size\_t. If the alignment parameter is not a power of two or is less than the default alignment of the allocator (that can be found out using routine libAlign in CFA) then the passed alignment parameter will be rejected and the default alignment will be used.
     379This parameter is position-free and uses a backtick routine align (`align). The parameter passed with `align should be of type size_t. If the alignment parameter is not a power of two or is less than the default alignment of the allocator (that can be found out using routine libAlign in CFA) then the passed alignment parameter will be rejected and the default alignment will be used.
    401380
    402381Example: int b = alloc( 5 , 64`align )
     
    406385This parameter is position-free and uses a backtick routine fill (`fill). In case of realloc, only the extra space after copying the data in the old object will be filled with given parameter.
    407386Three types of parameters can be passed using `fill.
    408 
    409387\begin{itemize}
    410388\item
  • doc/theses/mubeen_zulfiqar_MMath/background.tex

    ra2e4b0c ra51a02d  
    2323====================
    2424
    25 \section{Background}
    26 
    27 % FIXME: cite wasik
    28 \cite{wasik.thesis}
    29 
    30 \subsection{Memory Allocation}
    31 With dynamic allocation being an important feature of C, there are many standalone memory allocators that have been designed for different purposes. For this thesis, we chose 7 of the most popular and widely used memory allocators.
    32 
    33 \paragraph{dlmalloc}
    34 dlmalloc (FIX ME: cite allocator) is a thread-safe allocator that is single threaded and single heap. dlmalloc maintains free-lists of different sizes to store freed dynamic memory. (FIX ME: cite wasik)
    35 
    36 \paragraph{hoard}
    37 Hoard (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and using a heap layer framework. It has per-thred heaps that have thread-local free-lists, and a gloabl shared heap. (FIX ME: cite wasik)
    38 
    39 \paragraph{jemalloc}
    40 jemalloc (FIX ME: cite allocator) is a thread-safe allocator that uses multiple arenas. Each thread is assigned an arena. Each arena has chunks that contain contagious memory regions of same size. An arena has multiple chunks that contain regions of multiple sizes.
    41 
    42 \paragraph{ptmalloc}
    43 ptmalloc (FIX ME: cite allocator) is a modification of dlmalloc. It is a thread-safe multi-threaded memory allocator that uses multiple heaps. ptmalloc heap has similar design to dlmalloc's heap.
    44 
    45 \paragraph{rpmalloc}
    46 rpmalloc (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and uses per-thread heap. Each heap has multiple size-classes and each size-calss contains memory regions of the relevant size.
    47 
    48 \paragraph{tbb malloc}
    49 tbb malloc (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and uses private heap for each thread. Each private-heap has multiple bins of different sizes. Each bin contains free regions of the same size.
    50 
    51 \paragraph{tc malloc}
    52 tcmalloc (FIX ME: cite allocator) is a thread-safe allocator. It uses per-thread cache to store free objects that prevents contention on shared resources in multi-threaded application. A central free-list is used to refill per-thread cache when it gets empty.
    53 
    54 \subsection{Benchmarks}
    55 There are multiple benchmarks that are built individually and evaluate different aspects of a memory allocator. But, there is not standard set of benchamrks that can be used to evaluate multiple aspects of memory allocators.
    56 
    57 \paragraph{threadtest}
    58 (FIX ME: cite benchmark and hoard) Each thread repeatedly allocates and then deallocates 100,000 objects. Runtime of the benchmark evaluates its efficiency.
    59 
    60 \paragraph{shbench}
    61 (FIX ME: cite benchmark and hoard) Each thread allocates and randomly frees a number of random-sized objects. It is a stress test that also uses runtime to determine efficiency of the allocator.
    62 
    63 \paragraph{larson}
    64 (FIX ME: cite benchmark and hoard) Larson simulates a server environment. Multiple threads are created where each thread allocator and free a number of objects within a size range. Some objects are passed from threads to the child threads to free. It caluculates memory operations per second as an indicator of memory allocator's performance.
     25\cite{Wasik08}
  • doc/theses/mubeen_zulfiqar_MMath/benchmarks.tex

    ra2e4b0c ra51a02d  
    149149*** FIX ME: Insert a figure of above benchmark with description
    150150
    151 \paragraph{Relevant Knobs}
     151\paragrpah{Relevant Knobs}
    152152*** FIX ME: Insert Relevant Knobs
    153153
  • doc/theses/mubeen_zulfiqar_MMath/intro.tex

    ra2e4b0c ra51a02d  
    4747\begin{itemize}
    4848\item
    49 aligned\_alloc
     49aligned_alloc
    5050\item
    51 malloc\_usable\_size
     51malloc_usable_size
    5252\item
    5353memalign
    5454\item
    55 posix\_memalign
     55posix_memalign
    5656\item
    5757pvalloc
     
    6161
    6262With the rise of concurrent applications, memory allocators should be able to fulfill dynamic memory requests from multiple threads in parallel without causing contention on shared resources. There needs to be a set of a standard benchmarks that can be used to evaluate an allocator's performance in different scenerios.
     63
     64\section{Background}
     65
     66\subsection{Memory Allocation}
     67With dynamic allocation being an important feature of C, there are many standalone memory allocators that have been designed for different purposes. For this thesis, we chose 7 of the most popular and widely used memory allocators.
     68
     69\paragraph{dlmalloc}
     70dlmalloc (FIX ME: cite allocator) is a thread-safe allocator that is single threaded and single heap. dlmalloc maintains free-lists of different sizes to store freed dynamic memory. (FIX ME: cite wasik)
     71
     72\paragraph{hoard}
     73Hoard (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and using a heap layer framework. It has per-thred heaps that have thread-local free-lists, and a gloabl shared heap. (FIX ME: cite wasik)
     74
     75\paragraph{jemalloc}
     76jemalloc (FIX ME: cite allocator) is a thread-safe allocator that uses multiple arenas. Each thread is assigned an arena. Each arena has chunks that contain contagious memory regions of same size. An arena has multiple chunks that contain regions of multiple sizes.
     77
     78\paragraph{ptmalloc}
     79ptmalloc (FIX ME: cite allocator) is a modification of dlmalloc. It is a thread-safe multi-threaded memory allocator that uses multiple heaps. ptmalloc heap has similar design to dlmalloc's heap.
     80
     81\paragraph{rpmalloc}
     82rpmalloc (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and uses per-thread heap. Each heap has multiple size-classes and each size-calss contains memory regions of the relevant size.
     83
     84\paragraph{tbb malloc}
     85tbb malloc (FIX ME: cite allocator) is a thread-safe allocator that is multi-threaded and uses private heap for each thread. Each private-heap has multiple bins of different sizes. Each bin contains free regions of the same size.
     86
     87\paragraph{tc malloc}
     88tcmalloc (FIX ME: cite allocator) is a thread-safe allocator. It uses per-thread cache to store free objects that prevents contention on shared resources in multi-threaded application. A central free-list is used to refill per-thread cache when it gets empty.
     89
     90\subsection{Benchmarks}
     91There are multiple benchmarks that are built individually and evaluate different aspects of a memory allocator. But, there is not standard set of benchamrks that can be used to evaluate multiple aspects of memory allocators.
     92
     93\paragraph{threadtest}
     94(FIX ME: cite benchmark and hoard) Each thread repeatedly allocates and then deallocates 100,000 objects. Runtime of the benchmark evaluates its efficiency.
     95
     96\paragraph{shbench}
     97(FIX ME: cite benchmark and hoard) Each thread allocates and randomly frees a number of random-sized objects. It is a stress test that also uses runtime to determine efficiency of the allocator.
     98
     99\paragraph{larson}
     100(FIX ME: cite benchmark and hoard) Larson simulates a server environment. Multiple threads are created where each thread allocator and free a number of objects within a size range. Some objects are passed from threads to the child threads to free. It caluculates memory operations per second as an indicator of memory allocator's performance.
    63101
    64102\section{Research Objectives}
  • doc/theses/mubeen_zulfiqar_MMath/performance.tex

    ra2e4b0c ra51a02d  
    4444tc               &             &  \\
    4545\end{tabularx}
    46 
    47 %(FIX ME: complete table)
     46(FIX ME: complete table)
    4847
    4948\section{Experiment Environment}
  • doc/theses/mubeen_zulfiqar_MMath/uw-ethesis.bib

    ra2e4b0c ra51a02d  
    2727        address =       "Reading, Massachusetts"
    2828}
    29 
    30 @article{wasik.thesis,
    31     author        = "Ayelet Wasik",
    32     title         = "Features of A Multi-Threaded Memory Alloator",
    33     publisher     = "University of Waterloo",
    34     year          = "2008"
    35 }
  • doc/theses/mubeen_zulfiqar_MMath/uw-ethesis.tex

    ra2e4b0c ra51a02d  
    8484\usepackage{graphicx}
    8585\usepackage{comment} % Removes large sections of the document.
    86 \usepackage{tabularx}
    8786
    8887% Hyperlinks make it very easy to navigate an electronic document.
     
    192191% Tip: Putting each sentence on a new line is a way to simplify later editing.
    193192%----------------------------------------------------------------------
    194 \begin{sloppypar}
    195 
    196193\input{intro}
    197194\input{background}
     
    200197\input{performance}
    201198\input{conclusion}
    202 
    203 \end{sloppypar}
    204199
    205200%----------------------------------------------------------------------
  • doc/user/user.tex

    ra2e4b0c ra51a02d  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Oct 10 12:45:00 2021
    14 %% Update Count     : 5095
     13%% Last Modified On : Mon May 31 09:03:34 2021
     14%% Update Count     : 5071
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    44444444\CFA provides a fine-grained solution where a \Index{recursive lock} is acquired and released indirectly via a manipulator ©acquire© or instantiating an \Index{RAII} type specific for the kind of stream: ©osacquire©\index{ostream@©ostream©!osacquire@©osacquire©} for output streams and ©isacquire©\index{isacquire@©isacquire©}\index{istream@©istream©!isacquire@©isacquire©} for input streams.
    44454445
    4446 The common usage is the short form of the mutex statement\index{ostream@©ostream©!mutex@©mutex©} to lock a stream during a single cascaded I/O expression, \eg:
    4447 \begin{cfa}
    4448 $\emph{thread\(_1\)}$ : ®mutex()® sout | "abc " | "def ";
    4449 $\emph{thread\(_2\)}$ : ®mutex()® sout | "uvw " | "xyz ";
     4446The common usage is manipulator ©acquire©\index{ostream@©ostream©!acquire@©acquire©} to lock a stream during a single cascaded I/O expression, with the manipulator appearing as the first item in a cascade list, \eg:
     4447\begin{cfa}
     4448$\emph{thread\(_1\)}$ : sout | ®acquire® | "abc " | "def ";   // manipulator
     4449$\emph{thread\(_2\)}$ : sout | ®acquire® | "uvw " | "xyz ";
    44504450\end{cfa}
    44514451Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order.
     
    44664466In summary, the stream lock is acquired by the ©acquire© manipulator and implicitly released at the end of the cascaded I/O expression ensuring all operations in the expression occur atomically.
    44674467
    4468 To lock a stream across multiple I/O operations, he long form of the mutex statement is used, \eg:
    4469 \begin{cfa}
    4470 ®mutex( sout )® {
     4468To lock a stream across multiple I/O operations, an object of type ©osacquire© or ©isacquire© is declared to implicitly acquire/release the stream lock providing mutual exclusion for the object's duration, \eg:
     4469\begin{cfa}
     4470{       // acquire sout for block duration
     4471        ®osacquire® acq = { sout };                             $\C{// named stream locker}$
    44714472        sout | 1;
    4472         ®mutex() sout® | 2 | 3;                         $\C{// unnecessary, but ok because of recursive lock}$
     4473        sout | ®acquire® | 2 | 3;                               $\C{// unnecessary, but ok to acquire and release again}$
    44734474        sout | 4;
    4474 } // implicitly release sout lock
    4475 \end{cfa}
    4476 Note, the unnecessary ©mutex© in the middle of the mutex statement, works because the recursive stream-lock can be acquired/released multiple times by the owner thread.
     4475}       // implicitly release the lock when "acq" is deallocated
     4476\end{cfa}
     4477Note, the unnecessary ©acquire© manipulator works because the recursive stream-lock can be acquired/released multiple times by the owner thread.
    44774478Hence, calls to functions that also acquire a stream lock for their output do not result in \Index{deadlock}.
    44784479
    44794480The previous values written by threads 1 and 2 can be read in concurrently:
    44804481\begin{cfa}
    4481 ®mutex( sin )® {
     4482{       // acquire sin lock for block duration
     4483        ®isacquire acq = { sin };®                              $\C{// named stream locker}$
    44824484        int x, y, z, w;
    44834485        sin | x;
    4484         ®mutex() sin® | y | z;                          $\C{// unnecessary, but ok because of recursive lock}$
     4486        sin | ®acquire® | y | z;                                $\C{// unnecessary, but ok to acquire and release again}$
    44854487        sin | w;
    4486 } // implicitly release sin lock
     4488}       // implicitly release the lock when "acq" is deallocated
    44874489\end{cfa}
    44884490Again, the order of the reading threads is non-deterministic.
     
    44914493\Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg:
    44924494\begin{cfa}
    4493 ®mutex() sout® | "data:" | rtn( mon );  $\C{// mutex call on monitor}$
     4495sout | ®acquire® | "data:" | rtn( mon );        $\C{// mutex call on monitor}$
    44944496\end{cfa}
    44954497If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it.
     
    44984500\begin{cfa}
    44994501int ®data® = rtn( mon );
    4500 mutex() sout | "data:" | ®data®;
     4502sout | acquire | "data:" | ®data®;
    45014503\end{cfa}
    45024504
     
    45044506\section{String Stream}
    45054507
    4506 The stream types ©ostrstream© and ©istrstream© provide all the stream formatting capabilities to/from a C string rather than a stream file.
    4507 \VRef[Figure]{f:StringStreamProcessing} shows writing (output) to and reading (input) from a C string.
    4508 The only string stream operations different from a file stream are:
    4509 \begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
    4510 \item
    4511 constructors to create a stream that writes to a write buffer (©ostrstream©) of ©size©, or reads from a read buffer (©istrstream©) containing a C string terminated with ©'\0'©.
    4512 \begin{cfa}
    4513 void ?{}( ostrstream &, char buf[], size_t size );
    4514 void ?{}( istrstream & is, char buf[] );
    4515 \end{cfa}
    4516 \item
    4517 \Indexc{write} (©ostrstream© only) writes all the buffered characters to the specified stream (©stdout© default).
    4518 \begin{cfa}
    4519 ostrstream & write( ostrstream & os, FILE * stream = stdout );
    4520 \end{cfa}
    4521 There is no ©read© for ©istrstream©.
    4522 \end{itemize}
    4523 
     4508All the stream formatting capabilities are available to format text to/from a C string rather than to a stream file.
     4509\VRef[Figure]{f:StringStreamProcessing} shows writing (output) and reading (input) from a C string.
    45244510\begin{figure}
    45254511\begin{cfa}
     
    45344520        double x = 12345678.9, y = 98765.4321e-11;
    45354521
    4536         osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc";
    4537         write( osstr ); $\C{// write string to stdout}$
    4538         printf( "%s", buf ); $\C{// same lines of output}$
    4539         sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc";
    4540 
    4541         char buf2[] = "12 14 15 3.5 7e4 abc"; $\C{// input buffer}$
     4522        osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)); $\C{// same lines of output}$
     4523        write( osstr );
     4524        printf( "%s", buf );
     4525        sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
     4526
     4527        char buf2[] = "12 14 15 3.5 7e4"; $\C{// input buffer}$
    45424528        ®istrstream isstr = { buf2 };®
    4543         char s[10];
    4544         isstr | i | j | k | x | y | s;
    4545         sout  | i | j | k | x | y | s;
    4546 }
    4547 
    4548 3 0x5          7 1.234568e+07 987.654n abc
    4549 3 0x5          7 1.234568e+07 987.654n abc
    4550 3 0x5          7 1.234568e+07 987.654n abc
    4551 12 14 15 3.5 70000. abc
     4529        isstr | i | j | k | x | y;
     4530        sout | i | j | k | x | y;
     4531}
    45524532\end{cfa}
    45534533\caption{String Stream Processing}
    45544534\label{f:StringStreamProcessing}
    45554535\end{figure}
     4536
     4537\VRef[Figure]{f:StringStreamFunctions} shows the string stream operations.
     4538\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     4539\item
     4540\Indexc{write} (©ostrstream© only) writes all the buffered characters to the specified stream (©stdout© default).
     4541\end{itemize}
     4542The constructor functions:
     4543\begin{itemize}[topsep=4pt,itemsep=2pt,parsep=0pt]
     4544\item
     4545create a bound stream to a write buffer (©ostrstream©) of ©size© or a read buffer (©istrstream©) containing a C string terminated with ©'\0'©.
     4546\end{itemize}
     4547
     4548\begin{figure}
     4549\begin{cfa}
     4550// *********************************** ostrstream ***********************************
     4551
     4552ostrstream & write( ostrstream & os, FILE * stream = stdout );
     4553
     4554void ?{}( ostrstream &, char buf[], size_t size );
     4555
     4556// *********************************** istrstream ***********************************
     4557
     4558void ?{}( istrstream & is, char buf[] );
     4559\end{cfa}
     4560\caption{String Stream Functions}
     4561\label{f:StringStreamFunctions}
     4562\end{figure}
     4563
    45564564
    45574565\begin{comment}
  • libcfa/src/fstream.cfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 11:23:05 2021
    13 // Update Count     : 512
     12// Last Modified On : Tue Sep 21 21:51:38 2021
     13// Update Count     : 460
    1414//
    1515
     
    2828#define IO_MSG "I/O error: "
    2929
    30 // private
    31 void ?{}( ofstream & os, void * file ) with( os ) {
     30void ?{}( ofstream & os, void * file ) with(os) {
    3231        file$ = file;
    3332        sepDefault$ = true;
     
    3635        prt$ = false;
    3736        sawNL$ = false;
     37        acquired$ = false;
    3838        sepSetCur$( os, sepGet( os ) );
    3939        sepSet( os, " " );
     
    4141} // ?{}
    4242
    43 inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
    44 inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; }
    45 inline void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
    46 inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; }
    47 inline void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
    48 inline bool getNL$( ofstream & os ) { return os.sawNL$; }
    49 inline void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; }
    50 inline bool getANL$( ofstream & os ) { return os.nlOnOff$; }
    51 inline bool getPrt$( ofstream & os ) { return os.prt$; }
    52 inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
    53 
    54 inline void lock( ofstream & os ) with( os ) {  lock( os.lock$ ); }
    55 inline void unlock( ofstream & os ) { unlock( os.lock$ ); }
     43// private
     44bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
     45void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; }
     46void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
     47const char * sepGetCur$( ofstream & os ) { return os.sepCur$; }
     48void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
     49bool getNL$( ofstream & os ) { return os.sawNL$; }
     50void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; }
     51bool getANL$( ofstream & os ) { return os.nlOnOff$; }
     52bool getPrt$( ofstream & os ) { return os.prt$; }
     53void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
    5654
    5755// public
    5856void ?{}( ofstream & os ) { os.file$ = 0p; }
    59 void ?{}( ofstream & os, const char name[], const char mode[] ) { open( os, name, mode ); }
    60 void ?{}( ofstream & os, const char name[] ) { open( os, name, "w" ); }
    61 void ^?{}( ofstream & os ) { close( os ); }
     57
     58void ?{}( ofstream & os, const char name[], const char mode[] ) {
     59        open( os, name, mode );
     60} // ?{}
     61
     62void ?{}( ofstream & os, const char name[] ) {
     63        open( os, name, "w" );
     64} // ?{}
     65
     66void ^?{}( ofstream & os ) {
     67        close( os );
     68} // ^?{}
    6269
    6370void sepOn( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
     
    100107        if ( &os == &exit ) exit( EXIT_FAILURE );
    101108        if ( &os == &abort ) abort();
     109        if ( os.acquired$ ) { os.acquired$ = false; release( os ); }
    102110} // ends
    103111
    104 bool fail( ofstream & os ) { return os.file$ == 0 || ferror( (FILE *)(os.file$) ); }
    105 void clear( ofstream & os ) { clearerr( (FILE *)(os.file$) ); }
    106 int flush( ofstream & os ) { return fflush( (FILE *)(os.file$) ); }
     112bool fail( ofstream & os ) {
     113        return os.file$ == 0 || ferror( (FILE *)(os.file$) );
     114} // fail
     115
     116void clear( ofstream & os ) {
     117        clearerr( (FILE *)(os.file$) );
     118} // clear
     119
     120int flush( ofstream & os ) {
     121        return fflush( (FILE *)(os.file$) );
     122} // flush
    107123
    108124void open( ofstream & os, const char name[], const char mode[] ) {
    109         FILE * file;
    110     for ( cnt; 10 ) {
    111                 errno = 0;
    112                 file = fopen( name, mode );
    113           if ( file != 0p || errno != EINTR ) break;            // timer interrupt ?
    114           if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" );
    115     } // for
     125        FILE * file = fopen( name, mode );
    116126        if ( file == 0p ) {
    117127                throw (Open_Failure){ os };
     
    121131} // open
    122132
    123 void open( ofstream & os, const char name[] ) { open( os, name, "w" ); }
    124 
    125 void close( ofstream & os ) with( os ) {
     133void open( ofstream & os, const char name[] ) {
     134        open( os, name, "w" );
     135} // open
     136
     137void close( ofstream & os ) with(os) {
    126138  if ( (FILE *)(file$) == 0p ) return;
    127139  if ( (FILE *)(file$) == (FILE *)stdout || (FILE *)(file$) == (FILE *)stderr ) return;
    128140
    129         int ret;
    130     for ( cnt; 10 ) {
    131                 errno = 0;
    132                 ret = fclose( (FILE *)(file$) );
    133           if ( ret != EOF || errno != EINTR ) break;            // timer interrupt ?
    134           if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" );
    135     } // for
    136         if ( ret == EOF ) {
     141        if ( fclose( (FILE *)(file$) ) == EOF ) {
    137142                throw (Close_Failure){ os };
    138143                // abort | IO_MSG "close output" | nl | strerror( errno );
    139144        } // if
    140         file$ = 0p;                                                                                     // safety after close
     145        file$ = 0p;
    141146} // close
    142147
     
    157162        va_list args;
    158163        va_start( args, format );
    159                
    160         int len;
    161     for ( cnt; 10 ) {
    162                 errno = 0;
    163                 len = vfprintf( (FILE *)(os.file$), format, args );
    164           if ( len != EOF || errno != EINTR ) break;            // timer interrupt ?
    165           if ( cnt == 9 ) abort( "ofstream fmt EINTR spinning exceeded" );
    166     } // for
     164        int len = vfprintf( (FILE *)(os.file$), format, args );
    167165        if ( len == EOF ) {
    168166                if ( ferror( (FILE *)(os.file$) ) ) {
     
    177175} // fmt
    178176
    179 <<<<<<< HEAD
    180177inline void acquire( ofstream & os ) with(os) {
    181178        lock( lock$ );                                                                          // may increase recursive lock
     
    194191void ^?{}( osacquire & acq ) { release( acq.os ); }
    195192
    196 =======
    197 >>>>>>> 15885de998d9500373efda8e609b893c87e6363a
    198193static ofstream soutFile = { (FILE *)stdout };
    199194ofstream & sout = soutFile, & stdout = soutFile;
     
    213208        flush( os );
    214209        return os;
     210        // (ofstream &)(os | '\n');
     211        // setPrt$( os, false );                                                        // turn off
     212        // setNL$( os, true );
     213        // flush( os );
     214        // return sepOff( os );                                                 // prepare for next line
    215215} // nl
    216216
     
    220220
    221221// private
    222 void ?{}( ifstream & is, void * file ) with( is ) {
     222void ?{}( ifstream & is, void * file ) with(is) {
    223223        file$ = file;
    224224        nlOnOff$ = false;
    225 } // ?{}
    226 
    227 bool getANL$( ifstream & os ) { return os.nlOnOff$; }
    228 
    229 inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); }
    230 inline void unlock( ifstream & os ) { unlock( os.lock$ ); }
     225        acquired$ = false;
     226} // ?{}
    231227
    232228// public
    233229void ?{}( ifstream & is ) { is.file$ = 0p; }
    234 void ?{}( ifstream & is, const char name[], const char mode[] ) { open( is, name, mode ); }
    235 void ?{}( ifstream & is, const char name[] ) { open( is, name, "r" ); }
    236 void ^?{}( ifstream & is ) { close( is ); }
    237 
    238 bool fail( ifstream & is ) { return is.file$ == 0p || ferror( (FILE *)(is.file$) ); }
    239 void clear( ifstream & is ) { clearerr( (FILE *)(is.file$) ); }
     230
     231void ?{}( ifstream & is, const char name[], const char mode[] ) {
     232        open( is, name, mode );
     233} // ?{}
     234
     235void ?{}( ifstream & is, const char name[] ) {
     236        open( is, name, "r" );
     237} // ?{}
     238
     239void ^?{}( ifstream & is ) {
     240        close( is );
     241} // ^?{}
    240242
    241243void nlOn( ifstream & os ) { os.nlOnOff$ = true; }
    242244void nlOff( ifstream & os ) { os.nlOnOff$ = false; }
    243 
    244 void ends( ifstream & is ) {}
    245 
    246 bool eof( ifstream & is ) { return feof( (FILE *)(is.file$) ) != 0; }
     245bool getANL( ifstream & os ) { return os.nlOnOff$; }
     246
     247bool fail( ifstream & is ) {
     248        return is.file$ == 0p || ferror( (FILE *)(is.file$) );
     249} // fail
     250
     251void clear( ifstream & is ) {
     252        clearerr( (FILE *)(is.file$) );
     253} // clear
     254
     255void ends( ifstream & is ) {
     256        if ( is.acquired$ ) { is.acquired$ = false; release( is ); }
     257} // ends
     258
     259bool eof( ifstream & is ) {
     260        return feof( (FILE *)(is.file$) );
     261} // eof
    247262
    248263void open( ifstream & is, const char name[], const char mode[] ) {
    249         FILE * file;
    250     for ( cnt; 10 ) {
    251                 errno = 0;
    252                 file = fopen( name, mode );
    253           if ( file != 0p || errno != EINTR ) break;            // timer interrupt ?
    254           if ( cnt == 9 ) abort( "ifstream open EINTR spinning exceeded" );
    255     } // for
     264        FILE * file = fopen( name, mode );
    256265        if ( file == 0p ) {
    257266                throw (Open_Failure){ is };
     
    261270} // open
    262271
    263 void open( ifstream & is, const char name[] ) { open( is, name, "r" ); }
    264 
    265 void close( ifstream & is ) with( is ) {
     272void open( ifstream & is, const char name[] ) {
     273        open( is, name, "r" );
     274} // open
     275
     276void close( ifstream & is ) with(is) {
    266277  if ( (FILE *)(file$) == 0p ) return;
    267278  if ( (FILE *)(file$) == (FILE *)stdin ) return;
    268279
    269         int ret;
    270     for ( cnt; 10 ) {
    271                 errno = 0;
    272                 ret = fclose( (FILE *)(file$) );
    273           if ( ret != EOF || errno != EINTR ) break;            // timer interrupt ?
    274           if ( cnt == 9 ) abort( "ifstream close EINTR spinning exceeded" );
    275     } // for
    276         if ( ret == EOF ) {
     280        if ( fclose( (FILE *)(file$) ) == EOF ) {
    277281                throw (Close_Failure){ is };
    278282                // abort | IO_MSG "close input" | nl | strerror( errno );
    279283        } // if
    280         file$ = 0p;                                                                                     // safety after close
     284        file$ = 0p;
    281285} // close
    282286
     
    307311int fmt( ifstream & is, const char format[], ... ) {
    308312        va_list args;
     313
    309314        va_start( args, format );
    310 
    311         int len;
    312     for () {                                                                                    // no check for EINTR limit waiting for keyboard input
    313                 errno = 0;
    314                 len = vfscanf( (FILE *)(is.file$), format, args );
    315           if ( len != EOF || errno != EINTR ) break;            // timer interrupt ?
    316     } // for
     315        int len = vfscanf( (FILE *)(is.file$), format, args );
    317316        if ( len == EOF ) {
    318317                if ( ferror( (FILE *)(is.file$) ) ) {
     
    323322        return len;
    324323} // fmt
     324
     325inline void acquire( ifstream & is ) with(is) {
     326        lock( lock$ );                                                                          // may increase recursive lock
     327        if ( ! acquired$ ) acquired$ = true;                            // not locked ?
     328        else unlock( lock$ );                                                           // unwind recursive lock at start
     329} // acquire
     330
     331inline void release( ifstream & is ) {
     332        unlock( is.lock$ );
     333} // release
     334
     335void ?{}( isacquire & acq, ifstream & is ) { lock( is.lock$ ); &acq.is = &is; }
     336void ^?{}( isacquire & acq ) { release( acq.is ); }
    325337
    326338static ifstream sinFile = { (FILE *)stdin };
  • libcfa/src/fstream.hfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 09:37:32 2021
    13 // Update Count     : 243
     12// Last Modified On : Wed Jul 28 07:35:50 2021
     13// Update Count     : 234
    1414//
    1515
     
    3636        char tupleSeparator$[ofstream_sepSize];
    3737        multiple_acquisition_lock lock$;
     38        bool acquired$;
    3839}; // ofstream
    3940
     
    5253void setPrt$( ofstream &, bool );
    5354
    54 void lock( ofstream & );
    55 void unlock( ofstream & );
    56 
    5755// public
    5856void sepOn( ofstream & );
     
    7775void open( ofstream &, const char name[] );
    7876void close( ofstream & );
    79 
    8077ofstream & write( ofstream &, const char data[], size_t size );
     78
     79void acquire( ofstream & );
     80void release( ofstream & );
     81
     82void lock( ofstream & );
     83void unlock( ofstream & );
     84
     85struct osacquire {
     86        ofstream & os;
     87};
     88void ?{}( osacquire & acq, ofstream & );
     89void ^?{}( osacquire & acq );
    8190
    8291void ?{}( ofstream & );
     
    101110        bool nlOnOff$;
    102111        multiple_acquisition_lock lock$;
     112        bool acquired$;
    103113}; // ifstream
    104114
    105115// Satisfies istream
    106 
    107 // private
    108 bool getANL$( ifstream & );
    109 
    110 void lock( ifstream & );
    111 void unlock( ifstream & );
    112116
    113117// public
    114118void nlOn( ifstream & );
    115119void nlOff( ifstream & );
     120bool getANL( ifstream & );
    116121void ends( ifstream & );
    117122int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     
    123128void open( ifstream & is, const char name[] );
    124129void close( ifstream & is );
    125 
    126130ifstream & read( ifstream & is, char data[], size_t size );
    127131ifstream & ungetc( ifstream & is, char c );
     132
     133void acquire( ifstream & is );
     134void release( ifstream & is );
     135
     136struct isacquire {
     137        ifstream & is;
     138};
     139void ?{}( isacquire & acq, ifstream & is );
     140void ^?{}( isacquire & acq );
    128141
    129142void ?{}( ifstream & is );
  • libcfa/src/iostream.cfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 09:28:17 2021
    13 // Update Count     : 1345
     12// Last Modified On : Sat May 15 09:39:21 2021
     13// Update Count     : 1342
    1414//
    1515
     
    398398                return os;
    399399        } // nlOff
     400} // distribution
     401
     402forall( ostype & | ostream( ostype ) ) {
     403        ostype & acquire( ostype & os ) {
     404                acquire( os );                                                                  // call void returning
     405                return os;
     406        } // acquire
    400407} // distribution
    401408
     
    822829                        fmt( is, "%c", &temp );                                         // must pass pointer through varg to fmt
    823830                        // do not overwrite parameter with newline unless appropriate
    824                         if ( temp != '\n' || getANL$( is ) ) { c = temp; break; }
     831                        if ( temp != '\n' || getANL( is ) ) { c = temp; break; }
    825832                        if ( eof( is ) ) break;
    826833                } // for
     
    10281035                return is;
    10291036        } // nlOff
     1037} // distribution
     1038
     1039forall( istype & | istream( istype ) ) {
     1040        istype & acquire( istype & is ) {
     1041                acquire( is );                                                                  // call void returning
     1042                return is;
     1043        } // acquire
    10301044} // distribution
    10311045
  • libcfa/src/iostream.hfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 10:02:07 2021
    13 // Update Count     : 407
     12// Last Modified On : Wed Apr 28 20:37:56 2021
     13// Update Count     : 401
    1414//
    1515
     
    5858        void close( ostype & );
    5959        ostype & write( ostype &, const char [], size_t );
     60        void acquire( ostype & );                                                       // concurrent access
    6061}; // ostream
    6162
     
    141142        ostype & nlOn( ostype & );
    142143        ostype & nlOff( ostype & );
     144} // distribution
     145
     146forall( ostype & | ostream( ostype ) ) {
     147        ostype & acquire( ostype & );
    143148} // distribution
    144149
     
    291296
    292297trait basic_istream( istype & ) {
    293         // private
    294         bool getANL$( istype & );                                                       // get scan newline (on/off)
    295         // public
     298        bool getANL( istype & );                                                        // get scan newline (on/off)
    296299        void nlOn( istype & );                                                          // read newline
    297300        void nlOff( istype & );                                                         // scan newline
     301
    298302        void ends( istype & os );                                                       // end of output statement
    299303        int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     
    308312        void close( istype & is );
    309313        istype & read( istype &, char [], size_t );
     314        void acquire( istype & );                                                       // concurrent access
    310315}; // istream
    311316
     
    374379} // distribution
    375380
     381forall( istype & | istream( istype ) ) {
     382        istype & acquire( istype & );
     383} // distribution
     384
    376385// *********************************** manipulators ***********************************
    377386
  • libcfa/src/strstream.cfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Thu Apr 22 22:24:35 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 16:13:20 2021
    13 // Update Count     : 101
     12// Last Modified On : Tue Apr 27 20:59:53 2021
     13// Update Count     : 78
    1414//
    1515
    1616#include "strstream.hfa"
    17 #include "fstream.hfa"                                                                  // abort
    1817
    1918#include <stdio.h>                                                                              // vsnprintf
     
    3130
    3231// private
    33 inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
    34 inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
    35 inline void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
    36 inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
    37 inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
    38 inline bool getNL$( ostrstream & os ) { return os.sawNL$; }
    39 inline void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
    40 inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
    41 inline bool getPrt$( ostrstream & os ) { return os.prt$; }
    42 inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
     32bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
     33void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
     34void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
     35const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
     36void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
     37bool getNL$( ostrstream & os ) { return os.sawNL$; }
     38void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
     39bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
     40bool getPrt$( ostrstream & os ) { return os.prt$; }
     41void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
    4342
    4443// public
     
    129128// *********************************** istrstream ***********************************
    130129
    131 // private
    132 bool getANL$( istrstream & is ) { return is.nlOnOff$; }
    133130
    134131// public
     
    139136} // ?{}
    140137
     138bool getANL( istrstream & is ) { return is.nlOnOff$; }
    141139void nlOn( istrstream & is ) { is.nlOnOff$ = true; }
    142140void nlOff( istrstream & is ) { is.nlOnOff$ = false; }
    143141
    144 void ends( istrstream & is ) {}
    145 bool eof( istrstream & is ) { return false; }
     142void ends( istrstream & is ) {
     143} // ends
    146144
    147 int fmt( istrstream & is, const char format[], ... ) with(is) {
    148         va_list args;
    149         va_start( args, format );
    150         // THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED.
    151         int len = vsscanf( buf$ + cursor$, format, args );
    152         va_end( args );
    153         if ( len == EOF ) {
    154                 abort | IO_MSG "invalid read";
    155         } // if
    156         // SKULLDUGGERY: This hack skips over characters read by vsscanf by moving to the next whitespace but it does not
    157         // handle C reads with wdi manipulators that leave the cursor at a non-whitespace character.
    158         for ( ; buf$[cursor$] != ' ' && buf$[cursor$] != '\t' && buf$[cursor$] != '\0'; cursor$ += 1 ) {
    159                 //printf( "X \'%c\'\n", buf$[cursor$] );
    160         } // for
    161         if ( buf$[cursor$] != '\0' ) cursor$ += 1;      // advance to whitespace
    162         return len;
    163 } // fmt
     145int eof( istrstream & is ) {
     146        return 0;
     147} // eof
    164148
    165149istrstream &ungetc( istrstream & is, char c ) {
     
    170154} // ungetc
    171155
     156int fmt( istrstream & is, const char format[], ... ) {
     157        va_list args;
     158        va_start( args, format );
     159        // This does not work because vsscanf does not return buffer position.
     160        int len = vsscanf( is.buf$ + is.cursor$, format, args );
     161        va_end( args );
     162        if ( len == EOF ) {
     163                int j;
     164                printf( "X %d%n\n", len, &j );
     165        } // if
     166        is.cursor$ += len;
     167        return len;
     168} // fmt
     169
    172170// Local Variables: //
    173171// tab-width: 4 //
  • libcfa/src/strstream.hfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Thu Apr 22 22:20:59 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 10:14:22 2021
    13 // Update Count     : 47
     12// Last Modified On : Tue Apr 27 20:58:50 2021
     13// Update Count     : 41
    1414//
    1515
     
    8585// Satisfies basic_istream
    8686
    87 // private
    88 bool getANL$( istrstream & );
    89 
    9087// public
     88bool getANL( istrstream & );
    9189void nlOn( istrstream & );
    9290void nlOff( istrstream & );
    9391void ends( istrstream & );
     92int fmt( istrstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
     93istrstream & ungetc( istrstream & is, char c );
     94int eof( istrstream & is );
    9495
    95 int fmt( istrstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
    96 istrstream & ungetc( istrstream &, char );
    97 bool eof( istrstream & );
    98 
    99 void ?{}( istrstream &, char buf[] );
     96void ?{}( istrstream & is, char buf[] );
    10097
    10198// Local Variables: //
  • src/AST/Pass.hpp

    ra2e4b0c ra51a02d  
    348348
    349349        /// When this node is finished being visited, restore the value of a variable
    350         /// You may assign to the return value to set the new value in the same statement.
    351350        template< typename T >
    352         T& GuardValue( T& val ) {
     351        void GuardValue( T& val ) {
    353352                at_cleanup( [ val ]( void * newVal ) {
    354353                        * static_cast< T * >( newVal ) = val;
    355354                }, static_cast< void * >( & val ) );
    356                 return val;
    357355        }
    358356
     
    396394};
    397395
    398 /// Used to get a pointer to the wrapping TranslationUnit.
    399 struct WithConstTranslationUnit {
    400         const TranslationUnit * translationUnit = nullptr;
    401 
    402         const TranslationUnit & transUnit() const {
    403                 assertf( translationUnit, "WithConstTranslationUnit not set-up." );
    404                 return *translationUnit;
    405         }
    406 };
    407 
    408396}
    409397
  • src/AST/Pass.impl.hpp

    ra2e4b0c ra51a02d  
    420420template< typename core_t >
    421421inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
    422         if ( auto ptr = __pass::translation_unit::get_cptr( visitor.core, 0 ) ) {
    423                 ValueGuard<const TranslationUnit *> guard( *ptr );
    424                 *ptr = &unit;
    425                 return ast::accept_all( unit.decls, visitor );
    426         } else {
    427                 return ast::accept_all( unit.decls, visitor );
    428         }
     422        return ast::accept_all( unit.decls, visitor );
    429423}
    430424
  • src/AST/Pass.proto.hpp

    ra2e4b0c ra51a02d  
    426426        } // namespace forall
    427427
    428         // For passes that need access to the global context. Sreaches `translationUnit`
    429         namespace translation_unit {
    430                 template<typename core_t>
    431                 static inline auto get_cptr( core_t & core, int )
    432                                 -> decltype( &core.translationUnit ) {
    433                         return &core.translationUnit;
    434                 }
    435 
    436                 template<typename core_t>
    437                 static inline const TranslationUnit ** get_cptr( core_t &, long ) {
    438                         return nullptr;
    439                 }
    440         }
    441 
    442428        template<typename core_t>
    443429        static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
  • src/AST/TranslationUnit.hpp

    ra2e4b0c ra51a02d  
    2626        std::list< ptr< Decl > > decls;
    2727
    28         struct Global {
     28        struct Globals {
    2929                std::map< UniqueId, Decl * > idMap;
    3030
    31                 ptr<Type> sizeType;
     31                const Type * sizeType;
    3232                const FunctionDecl * dereference;
    3333                const StructDecl * dtorStruct;
  • src/AST/porting.md

    ra2e4b0c ra51a02d  
    9898        * `Initializer` => `ast::Init`
    9999    * `Statement` => `ast::Stmt`
    100     * `ReferenceToType` => `ast::BaseInstType`
    101100        * any field names should follow a similar renaming
    102101  * because they don't really belong to `Type` (and for consistency with `Linkage::Spec`):
  • src/CodeTools/DeclStats.cc

    ra2e4b0c ra51a02d  
    156156                /// number of counting bins for linkages
    157157                static const unsigned n_named_specs = 8;
    158                 /// Mapping function from linkage to bin.
    159                 static unsigned linkage_index( LinkageSpec::Spec spec ) {
    160                         switch ( spec ) {
    161                         case LinkageSpec::Intrinsic:  return 0;
    162                         case LinkageSpec::C:          return 1;
    163                         case LinkageSpec::Cforall:    return 2;
    164                         case LinkageSpec::AutoGen:    return 3;
    165                         case LinkageSpec::Compiler:   return 4;
    166                         case LinkageSpec::BuiltinCFA: return 5;
    167                         case LinkageSpec::BuiltinC:   return 6;
    168                         default:                      return 7;
    169                         }
    170                 }
     158                /// map from total number of specs to bins
     159                static const unsigned ind_for_linkage[16];
    171160
    172161                Stats for_linkage[n_named_specs];            ///< Stores separate stats per linkage
     
    377366                        const std::string& mangleName = decl->get_mangleName().empty() ? decl->name : decl->get_mangleName();
    378367                        if ( seen_names.insert( mangleName ).second ) {
    379                                 Stats& stats = for_linkage[ linkage_index( decl->linkage ) ];
     368                                Stats& stats = for_linkage[ ind_for_linkage[ decl->linkage ] ];
    380369
    381370                                ++stats.n_decls;
     
    538527        };
    539528
     529        const unsigned DeclStats::ind_for_linkage[]
     530                = { 7, 7, 2, 1,   7, 7, 7, 3,   4, 7, 6, 5,   7, 7, 7, 0 };
     531
    540532        void printDeclStats( std::list< Declaration * > &translationUnit ) {
    541533                PassVisitor<DeclStats> stats;
  • src/Common/module.mk

    ra2e4b0c ra51a02d  
    2222      Common/CompilerError.h \
    2323      Common/Debug.h \
    24       Common/DeclStats.hpp \
    25       Common/DeclStats.cpp \
    2624      Common/ErrorObjects.h \
    2725      Common/Eval.cc \
     
    3533      Common/PassVisitor.proto.h \
    3634      Common/PersistentMap.h \
    37       Common/ResolvProtoDump.hpp \
    38       Common/ResolvProtoDump.cpp \
    3935      Common/ScopedMap.h \
    4036      Common/SemanticError.cc \
  • src/InitTweak/GenInit.cc

    ra2e4b0c ra51a02d  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Oct 25 13:53:00 2021
    13 // Update Count     : 186
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 23:15:10 2019
     13// Update Count     : 184
    1414//
    1515#include "GenInit.h"
     
    2424#include "AST/Decl.hpp"
    2525#include "AST/Init.hpp"
    26 #include "AST/Pass.hpp"
    2726#include "AST/Node.hpp"
    2827#include "AST/Stmt.hpp"
     
    295294        }
    296295
    297 namespace {
    298 
    299 #       warning Remove the _New suffix after the conversion is complete.
    300         struct HoistArrayDimension_NoResolve_New final :
    301                         public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting,
    302                         public ast::WithGuards, public ast::WithConstTranslationUnit,
    303                         public ast::WithVisitorRef<HoistArrayDimension_NoResolve_New> {
    304                 void previsit( const ast::ObjectDecl * decl );
    305                 const ast::DeclWithType * postvisit( const ast::ObjectDecl * decl );
    306                 // Do not look for objects inside there declarations (and type).
    307                 void previsit( const ast::AggregateDecl * ) { visit_children = false; }
    308                 void previsit( const ast::NamedTypeDecl * ) { visit_children = false; }
    309                 void previsit( const ast::FunctionType * ) { visit_children = false; }
    310 
    311                 const ast::Type * hoist( const ast::Type * type );
    312 
    313                 ast::Storage::Classes storageClasses;
    314         };
    315 
    316         void HoistArrayDimension_NoResolve_New::previsit(
    317                         const ast::ObjectDecl * decl ) {
    318                 GuardValue( storageClasses ) = decl->storage;
    319         }
    320 
    321         const ast::DeclWithType * HoistArrayDimension_NoResolve_New::postvisit(
    322                         const ast::ObjectDecl * objectDecl ) {
    323                 return mutate_field( objectDecl, &ast::ObjectDecl::type,
    324                                 hoist( objectDecl->type ) );
    325         }
    326 
    327         const ast::Type * HoistArrayDimension_NoResolve_New::hoist(
    328                         const ast::Type * type ) {
    329                 static UniqueName dimensionName( "_array_dim" );
    330 
    331                 if ( !isInFunction() || storageClasses.is_static ) {
    332                         return type;
    333                 }
    334 
    335                 if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    336                         if ( nullptr == arrayType->dimension ) {
    337                                 return type;
    338                         }
    339 
    340                         if ( !Tuples::maybeImpure( arrayType->dimension ) ) {
    341                                 return type;
    342                         }
    343 
    344                         ast::ptr<ast::Type> dimType = transUnit().global.sizeType;
    345                         assert( dimType );
    346                         add_qualifiers( dimType, ast::CV::Qualifiers( ast::CV::Const ) );
    347 
    348                         ast::ObjectDecl * arrayDimension = new ast::ObjectDecl(
    349                                 arrayType->dimension->location,
    350                                 dimensionName.newName(),
    351                                 dimType,
    352                                 new ast::SingleInit(
    353                                         arrayType->dimension->location,
    354                                         arrayType->dimension
    355                                 )
    356                         );
    357 
    358                         ast::ArrayType * mutType = ast::mutate( arrayType );
    359                         mutType->dimension = new ast::VariableExpr(
    360                                         arrayDimension->location, arrayDimension );
    361                         declsToAddBefore.push_back( arrayDimension );
    362 
    363                         mutType->base = hoist( mutType->base );
    364                         return mutType;
    365                 }
    366                 return type;
    367         }
    368 
    369         struct ReturnFixer_New final :
    370                         public ast::WithStmtsToAdd<>, ast::WithGuards {
    371                 void previsit( const ast::FunctionDecl * decl );
    372                 const ast::ReturnStmt * previsit( const ast::ReturnStmt * stmt );
    373         private:
    374                 const ast::FunctionDecl * funcDecl = nullptr;
    375         };
    376 
    377         void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
    378                 GuardValue( funcDecl ) = decl;
    379         }
    380 
    381         const ast::ReturnStmt * ReturnFixer_New::previsit(
    382                         const ast::ReturnStmt * stmt ) {
    383                 auto & returns = funcDecl->returns;
    384                 assert( returns.size() < 2 );
    385                 // Hands off if the function returns a reference.
    386                 // Don't allocate a temporary if the address is returned.
    387                 if ( stmt->expr && 1 == returns.size() ) {
    388                         ast::ptr<ast::DeclWithType> retDecl = returns.front();
    389                         if ( isConstructable( retDecl->get_type() ) ) {
    390                                 // Explicitly construct the return value using the return
    391                                 // expression and the retVal object.
    392                                 assertf( "" != retDecl->name,
    393                                         "Function %s has unnamed return value.\n",
    394                                         funcDecl->name.c_str() );
    395 
    396                                 auto retVal = retDecl.strict_as<ast::ObjectDecl>();
    397                                 if ( auto varExpr = stmt->expr.as<ast::VariableExpr>() ) {
    398                                         // Check if the return statement is already set up.
    399                                         if ( varExpr->var == retVal ) return stmt;
    400                                 }
    401                                 ast::ptr<ast::Stmt> ctorStmt = genCtorDtor(
    402                                         retVal->location, "?{}", retVal, stmt->expr );
    403                                 assertf( ctorStmt,
    404                                         "ReturnFixer: genCtorDtor returned nllptr: %s / %s",
    405                                         toString( retVal ).c_str(),
    406                                         toString( stmt->expr ).c_str() );
    407                                         stmtsToAddBefore.push_back( ctorStmt );
    408 
    409                                 // Return the retVal object.
    410                                 ast::ReturnStmt * mutStmt = ast::mutate( stmt );
    411                                 mutStmt->expr = new ast::VariableExpr(
    412                                         stmt->location, retDecl );
    413                                 return mutStmt;
    414                         }
    415                 }
    416                 return stmt;
    417         }
    418 
    419 } // namespace
    420 
    421         void genInit( ast::TranslationUnit & transUnit ) {
    422                 ast::Pass<HoistArrayDimension_NoResolve_New>::run( transUnit );
    423                 ast::Pass<ReturnFixer_New>::run( transUnit );
    424         }
    425 
    426296        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
    427297                PassVisitor<CtorDtor> ctordtor;
  • src/InitTweak/GenInit.h

    ra2e4b0c ra51a02d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct 22 16:08:00 2021
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:31:19 2017
     13// Update Count     : 4
    1414//
    1515
     
    2727        /// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
    2828        void genInit( std::list< Declaration * > & translationUnit );
    29         void genInit( ast::TranslationUnit & translationUnit );
    3029
    3130        /// Converts return statements into copy constructor calls on the hidden return variable
  • src/Parser/parser.yy

    ra2e4b0c ra51a02d  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct 15 09:20:17 2021
    13 // Update Count     : 5163
     12// Last Modified On : Sat Sep 11 08:20:44 2021
     13// Update Count     : 5040
    1414//
    1515
     
    3131// from ANSI90 to ANSI11 C are marked with the comment "C99/C11".
    3232
    33 // This grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions. All of the
     33// This grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions All of the
    3434// syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall (CFA), which
    3535// fixes several of C's outstanding problems and extends C with many modern language concepts. All of the syntactic
     
    6969        // 2. String encodings are transformed into canonical form (one encoding at start) so the encoding can be found
    7070        //    without searching the string, e.g.: "abc" L"def" L"ghi" => L"abc" "def" "ghi". Multiple encodings must match,
    71         //    e.g., u"a" U"b" L"c" is disallowed.
     71        //    i.e., u"a" U"b" L"c" is disallowed.
    7272
    7373        if ( from[0] != '"' ) {                                                         // encoding ?
     
    310310%token ATassign                                                                                 // @=
    311311
    312 %type<tok> identifier                                   identifier_at                           identifier_or_type_name         attr_name
     312%type<tok> identifier
     313%type<tok> identifier_or_type_name  attr_name
    313314%type<tok> quasi_keyword
    314315%type<constant> string_literal
     
    326327%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    327328%type<en> comma_expression                              comma_expression_opt
    328 %type<en> argument_expression_list_opt  argument_expression_list        argument_expression                     default_initializer_opt
     329%type<en> argument_expression_list_opt  argument_expression                     default_initializer_opt
    329330%type<ifctl> if_control_expression
    330331%type<fctl> for_control_expression              for_control_expression_list
     
    558559        IDENTIFIER
    559560        | quasi_keyword
    560         ;
    561 
    562 identifier_at:
    563         identifier
    564561        | '@'                                                                                           // CFA
    565562                { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
     
    696693        // empty
    697694                { $$ = nullptr; }
    698         | argument_expression_list
    699         ;
    700 
    701 argument_expression_list:
    702         argument_expression
     695        | argument_expression
    703696        | argument_expression_list_opt ',' argument_expression
    704697                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
     
    738731        | FLOATINGconstant fraction_constants_opt
    739732                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    740         | identifier_at fraction_constants_opt                          // CFA, allow anonymous fields
     733        | identifier fraction_constants_opt
    741734                {
    742735                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    10911084        comma_expression_opt ';'
    10921085                { $$ = new StatementNode( build_expr( $1 ) ); }
    1093         | MUTEX '(' ')' comma_expression ';'
    1094                 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
    1095                 // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }
    10961086        ;
    10971087
     
    11921182
    11931183iteration_statement:
    1194         WHILE '(' ')' statement                                                         // CFA => while ( 1 )
     1184        WHILE '(' push if_control_expression ')' statement pop
     1185                { $$ = new StatementNode( build_while( $4, maybe_build_compound( $6 ) ) ); }
     1186        | WHILE '(' ')' statement                                                       // CFA => while ( 1 )
    11951187                { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
    1196         | WHILE '(' if_control_expression ')' statement         %prec THEN
    1197                 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
    1198         | WHILE '(' if_control_expression ')' statement ELSE statement // CFA
    1199                 { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
     1188        | DO statement WHILE '(' comma_expression ')' ';'
     1189                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    12001190        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    12011191                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
    1202         | DO statement WHILE '(' comma_expression ')' ';'       %prec THEN
    1203                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    1204         | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1205                 { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
     1192        | FOR '(' push for_control_expression_list ')' statement pop
     1193                { $$ = new StatementNode( build_for( $4, maybe_build_compound( $6 ) ) ); }
    12061194        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    12071195                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
    1208         | FOR '(' for_control_expression_list ')' statement     %prec THEN
    1209                 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
    1210         | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1211                 { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12121196        ;
    12131197
     
    13551339with_statement:
    13561340        WITH '(' tuple_expression_list ')' statement
    1357                 { $$ = new StatementNode( build_with( $3, $5 ) ); }
     1341                {
     1342                        $$ = new StatementNode( build_with( $3, $5 ) );
     1343                }
    13581344        ;
    13591345
    13601346// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
    13611347mutex_statement:
    1362         MUTEX '(' argument_expression_list ')' statement
     1348        MUTEX '(' argument_expression_list_opt ')' statement
    13631349                { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
    13641350        ;
     
    24892475designation:
    24902476        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    2491         | identifier_at ':'                                                                     // GCC, field name
     2477        | identifier ':'                                                                        // GCC, field name
    24922478                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    24932479        ;
     
    25012487
    25022488designator:
    2503         '.' identifier_at                                                                       // C99, field name
     2489        '.' identifier                                                                          // C99, field name
    25042490                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    25052491        | '[' push assignment_expression pop ']'                        // C99, single array element
     
    29332919
    29342920paren_identifier:
    2935         identifier_at
     2921        identifier
    29362922                { $$ = DeclarationNode::newName( $1 ); }
    29372923        | '(' paren_identifier ')'                                                      // redundant parenthesis
  • src/main.cc

    ra2e4b0c ra51a02d  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct 22 16:06:00 2021
    13 // Update Count     : 653
     11// Last Modified By : Henry Xue
     12// Last Modified On : Mon Aug 23 15:42:08 2021
     13// Update Count     : 650
    1414//
    1515
     
    4343#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    4444#include "Common/CompilerError.h"           // for CompilerError
    45 #include "Common/DeclStats.hpp"             // for printDeclStats
    46 #include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4745#include "Common/Stats.h"
    4846#include "Common/PassVisitor.h"
     
    336334                PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    337335                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     336                PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
     337
     338                if ( libcfap ) {
     339                        // generate the bodies of cfa library functions
     340                        LibCfa::makeLibCfa( translationUnit );
     341                } // if
     342
     343                if ( declstatsp ) {
     344                        CodeTools::printDeclStats( translationUnit );
     345                        deleteAll( translationUnit );
     346                        return EXIT_SUCCESS;
     347                } // if
     348
     349                if ( bresolvep ) {
     350                        dump( translationUnit );
     351                        return EXIT_SUCCESS;
     352                } // if
    338353
    339354                CodeTools::fillLocations( translationUnit );
     355
     356                if ( resolvprotop ) {
     357                        CodeTools::dumpAsResolvProto( translationUnit );
     358                        return EXIT_SUCCESS;
     359                } // if
    340360
    341361                if( useNewAST ) {
     
    346366                        auto transUnit = convert( move( translationUnit ) );
    347367
    348                         forceFillCodeLocations( transUnit );
    349 
    350                         PASS( "Gen Init", InitTweak::genInit( transUnit ) );
    351368                        PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
    352 
    353                         if ( libcfap ) {
    354                                 // Generate the bodies of cfa library functions.
    355                                 LibCfa::makeLibCfa( transUnit );
    356                         } // if
    357 
    358                         if ( declstatsp ) {
    359                                 printDeclStats( transUnit );
    360                                 return EXIT_SUCCESS;
    361                         } // if
    362 
    363                         if ( bresolvep ) {
    364                                 dump( move( transUnit ) );
    365                                 return EXIT_SUCCESS;
    366                         } // if
    367 
    368                         if ( resolvprotop ) {
    369                                 dumpAsResolverProto( transUnit );
    370                                 return EXIT_SUCCESS;
    371                         } // if
    372 
     369                       
    373370                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    374371                        if ( exprp ) {
     
    380377
    381378                        PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
    382 
    383379                        translationUnit = convert( move( transUnit ) );
    384380                } else {
    385                         PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    386381                        PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
    387 
    388                         if ( libcfap ) {
    389                                 // Generate the bodies of cfa library functions.
    390                                 LibCfa::makeLibCfa( translationUnit );
    391                         } // if
    392 
    393                         if ( declstatsp ) {
    394                                 CodeTools::printDeclStats( translationUnit );
    395                                 deleteAll( translationUnit );
    396                                 return EXIT_SUCCESS;
    397                         } // if
    398 
    399                         if ( bresolvep ) {
    400                                 dump( translationUnit );
    401                                 return EXIT_SUCCESS;
    402                         } // if
    403 
    404                         CodeTools::fillLocations( translationUnit );
    405 
    406                         if ( resolvprotop ) {
    407                                 CodeTools::dumpAsResolvProto( translationUnit );
    408                                 return EXIT_SUCCESS;
    409                         } // if
    410382
    411383                        PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
  • tests/concurrent/semaphore.cfa

    ra2e4b0c ra51a02d  
    22#include <locks.hfa>
    33#include <thread.hfa>
    4 #include <mutex_stmt.hfa>
    54
    65enum { num_blockers = 17, num_unblockers = 13 };
     
    2928                thrash();
    3029                P(ben);
    31                 if(((thread&)this).seqable.next != 0p) mutex(sout) sout | "Link not invalidated";
     30                if(((thread&)this).seqable.next != 0p) sout | acquire |"Link not invalidated";
    3231                thrash();
    3332        }
  • tests/concurrent/sleep.cfa

    ra2e4b0c ra51a02d  
    11#include <fstream.hfa>
    22#include <thread.hfa>
    3 #include <mutex_stmt.hfa>
    43#include <time.hfa>
    54
     
    3029
    3130int main() {
    32         mutex( sout ) sout | "start";
     31        sout | acquire | "start";
    3332        {
    3433                slow_sleeper slow;
     
    3736                yield();
    3837        }
    39         mutex( sout ) sout | "done";
     38        sout | acquire | "done";
    4039}
    4140
  • tests/io/io-acquire.cfa

    ra2e4b0c ra51a02d  
    1010// Created On       : Mon Mar  1 18:40:09 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Oct  6 18:04:58 2021
    13 // Update Count     : 72
     12// Last Modified On : Tue Apr 27 11:49:34 2021
     13// Update Count     : 18
    1414//
    1515
    1616#include <fstream.hfa>
    1717#include <thread.hfa>
    18 #include <mutex_stmt.hfa>
    1918
    2019thread T {};
     
    2221        // output from parallel threads should not be scrambled
    2322
    24         for ( 100 ) {                                                                           // expression protection
    25                 mutex(sout) sout | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
     23        for ( 100 ) {                                                                           // local protection
     24                sout | acquire | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
    2625        }
    27         mutex( sout ) {                                                                         // statement protection
     26        {                                                                                                       // global protection (RAII)
     27                osacquire acq = { sout };
    2828                for ( 100 ) {
    2929                        sout | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
     
    3131        }
    3232        {                                                                                                       // duplicate protection demonstrating recursive lock
    33                 ofstream & h1( ofstream & os ) {                                // helper
    34                         mutex( os ) return os | 1 | 2 | 3 | 4;          // unnecessary mutex
    35                 }
    36                 ofstream & h2( ofstream & os ) {                                // helper
    37                         mutex( os ) return os | 6 | 7 | 8 | 9;          // unnecessary mutex
    38                 }
    39                 mutex( sout ) {                                                                 // unnecessary mutex
    40                         for ( 100 ) {
    41                                 mutex( sout ) {
    42                                         sout | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
    43                                         sout | h1 | 5 | h2;                                     // refactored code
    44                                 }
    45                         }
     33                osacquire acq = { sout };
     34                for ( 100 ) {
     35                        osacquire acq = { sout };
     36                        sout | acquire | 1 | 2 | 3 | 4 | 5 | acquire | 6 | 7 | 8 | 9;
     37                        sout | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
    4638                }
    4739        }
     
    5042
    5143        int a, b, c, d, e, f, g, h, i;
    52         for ( 100 ) {                                                                           // expression protection
    53                 mutex(sin) sin | a | b | c | d | e | f | g | h | i;
     44        for ( 100 ) {                                                                           // local protection
     45                sin | acquire | a | b | c | d | e | f | g | h | i;
    5446        }
    55         mutex( sin ) {                                                                          // statement protection
     47        {                                                                                                       // global protection (RAII)
     48                isacquire acq = { sin };
    5649                for ( 100 ) {
    5750                        sin  | a | b | c | d | e | f | g | h | i;
     
    5952        }
    6053        {                                                                                                       // duplicate protection demonstrating recursive lock
    61                 ifstream & h1( ifstream & is ) {                                // helper
    62                         mutex( is ) return is | a | b | c | d;          // unnecessary mutex
    63                 }
    64                 ifstream & h2( ifstream & is ) {                                // helper
    65                         mutex( is ) return is | f | g | h | i;          // unnecessary mutex
    66                 }
    67                 mutex( sin ) {                                                                  // unnecessary mutex
    68                         for ( 5 ) {
    69                                 mutex( sin ) {
    70                                         sin  | a | b | c | d | e | f | g | h | i;
    71                                         sin  | h1 | e | h2;                                     // refactored code
    72                                 }
    73                         }
     54                isacquire acq = { sin };
     55                for ( 100 ) {
     56                        isacquire acq = { sin };
     57                        sin | acquire | a | b | c | d | e | acquire | f | g | h | i;
     58                        sin | a | b | c | d | e | f | g | h | i;
    7459                }
    7560        }
  • tests/linking/io-acquire.cfa

    ra2e4b0c ra51a02d  
    1717#include <fstream.hfa>
    1818#include <stdlib.hfa>
    19 #include <mutex_stmt.hfa>
    2019
    2120int main() {
    2221        int i;
    2322        if(threading_enabled()) {
    24                 mutex( stdout ) stdout | "YES";
     23                stdout | acquire | "YES";
    2524                stdin | i;
    2625        } else {
    27                 mutex( stdout ) stdout | "NO";
     26                stdout | acquire | "NO";
    2827                stdin | i;
    2928        }
  • tests/pybin/test_run.py

    ra2e4b0c ra51a02d  
    6565        def toString( cls, retcode, duration ):
    6666                if settings.generating :
    67                         if   retcode == TestResult.SUCCESS:     key = 'pass'; text = "Done   "
    68                         elif retcode == TestResult.TIMEOUT:     key = 'time'; text = "TIMEOUT"
    69                         else :  key = 'fail';   text = "ERROR code %d" % retcode
     67                        if   retcode == TestResult.SUCCESS:     text = "Done   "
     68                        elif retcode == TestResult.TIMEOUT:     text = "TIMEOUT"
     69                        else :                                          text = "ERROR code %d" % retcode
    7070                else :
    71                         if   retcode == TestResult.SUCCESS:     key = 'pass'; text = "PASSED "
    72                         elif retcode == TestResult.TIMEOUT:     key = 'time'; text = "TIMEOUT"
    73                         else :  key = 'fail';   text = "FAILED with code %d" % retcode
     71                        if   retcode == TestResult.SUCCESS:     text = "PASSED "
     72                        elif retcode == TestResult.TIMEOUT:     text = "TIMEOUT"
     73                        else :                                          text = "FAILED with code %d" % retcode
    7474
    7575                text += "    C%s - R%s" % (fmtDur(duration[0]), fmtDur(duration[1]))
    76                 return key, text
     76                return text
  • tests/test.py

    ra2e4b0c ra51a02d  
    257257
    258258                # update output based on current action
    259                 result_key, result_txt = TestResult.toString( retcode, duration )
     259                result_txt = TestResult.toString( retcode, duration )
    260260
    261261                #print result with error if needed
     
    265265                        text = text + '\n' + error
    266266
    267                 return retcode == TestResult.SUCCESS, result_key, text
     267                return retcode == TestResult.SUCCESS, text
    268268        except KeyboardInterrupt:
    269                 return False, 'keybrd', ""
     269                return False, ""
    270270        # except Exception as ex:
    271271        #       print("Unexpected error in worker thread running {}: {}".format(t.target(), ex), file=sys.stderr)
     
    283283
    284284        failed = False
    285         rescnts = {     'pass': 0, 'fail': 0, 'time': 0, 'keybrd': 0 }
    286         other = 0
    287285
    288286        # for each test to run
     
    296294                )
    297295
    298                 for i, (succ, code, txt) in enumerate(timed(results, timeout = settings.timeout.total), 1) :
    299                         if code in rescnts.keys():
    300                                 rescnts[code] += 1
    301                         else:
    302                                 other += 1
    303 
     296                for i, (succ, txt) in enumerate(timed(results, timeout = settings.timeout.total), 1) :
    304297                        if not succ :
    305298                                failed = True
     
    326319        # clean the workspace
    327320        make('clean', output_file=subprocess.DEVNULL, error=subprocess.DEVNULL)
    328 
    329         print("{} passes, {} failures, {} timeouts, {} cancelled, {} other".format(rescnts['pass'], rescnts['fail'], rescnts['time'], rescnts['keybrd'], other))
    330321
    331322        return failed
     
    452443                        failed = run_tests(local_tests, options.jobs)
    453444                        if failed:
     445                                result = 1
    454446                                if not settings.continue_:
    455447                                        break
Note: See TracChangeset for help on using the changeset viewer.