Changeset 933f32f for libcfa


Ignore:
Timestamp:
May 24, 2019, 10:19:41 AM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
d908563
Parents:
6a9d4b4 (diff), 292642a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into cleanup-dtors

Location:
libcfa
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • libcfa/configure

    r6a9d4b4 r933f32f  
    23822382
    23832383
     2384# http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_check_compile_flag.m4
     2385
    23842386
    23852387am__api_version='1.15'
     
    29572959case $CONFIGURATION in
    29582960        "debug"   )
    2959                 CONFIG_CFLAGS="-O0 -g"
     2961                CONFIG_CFLAGS="-Og -g"
    29602962                CONFIG_CFAFLAGS="-debug"
    29612963                CONFIG_BUILDLIB="yes"
    29622964        ;;
    29632965        "nodebug" )
    2964                 CONFIG_CFLAGS="-O2 -s"
     2966                CONFIG_CFLAGS="-O3 -s"
    29652967                CONFIG_CFAFLAGS="-nodebug"
    29662968                CONFIG_BUILDLIB="yes"
    29672969        ;;
    29682970        "nolib"   )
    2969                 CONFIG_CFLAGS="-O2 -s"
     2971                CONFIG_CFLAGS="-O3 -s"
     2972                CONFIG_CFAFLAGS="-nolib"
     2973                CONFIG_BUILDLIB="no"
     2974        ;;
     2975        "profile" )
     2976                CONFIG_CFLAGS="-O3 -g -fno-omit-frame-pointer"
    29702977                CONFIG_CFAFLAGS="-nodebug"
    2971                 CONFIG_BUILDLIB="no"
     2978                CONFIG_BUILDLIB="yes"
    29722979        ;;
    29732980        *)
     
    29752982        ;;
    29762983esac
     2984
     2985CONFIG_CFAFLAGS="${CONFIG_CFAFLAGS} ${CFAFLAGS}"
    29772986
    29782987
  • libcfa/configure.ac

    r6a9d4b4 r933f32f  
    4545case $CONFIGURATION in
    4646        "debug"   )
    47                 CONFIG_CFLAGS="-O0 -g"
     47                CONFIG_CFLAGS="-Og -g"
    4848                CONFIG_CFAFLAGS="-debug"
    4949                CONFIG_BUILDLIB="yes"
    5050        ;;
    5151        "nodebug" )
    52                 CONFIG_CFLAGS="-O2 -s"
     52                CONFIG_CFLAGS="-O3 -s"
    5353                CONFIG_CFAFLAGS="-nodebug"
    5454                CONFIG_BUILDLIB="yes"
    5555        ;;
    5656        "nolib"   )
    57                 CONFIG_CFLAGS="-O2 -s"
     57                CONFIG_CFLAGS="-O3 -s"
     58                CONFIG_CFAFLAGS="-nolib"
     59                CONFIG_BUILDLIB="no"
     60        ;;
     61        "profile" )
     62                CONFIG_CFLAGS="-O3 -g -fno-omit-frame-pointer"
    5863                CONFIG_CFAFLAGS="-nodebug"
    59                 CONFIG_BUILDLIB="no"
     64                CONFIG_BUILDLIB="yes"
    6065        ;;
    6166        *)
     
    6368        ;;
    6469esac
     70
     71CONFIG_CFAFLAGS="${CONFIG_CFAFLAGS} ${CFAFLAGS}"
    6572
    6673AC_SUBST(CONFIG_CFLAGS)
  • libcfa/prelude/builtins.c

    r6a9d4b4 r933f32f  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  5 21:40:38 2018
    13 // Update Count     : 20
     12// Last Modified On : Tue Mar 26 23:10:36 2019
     13// Update Count     : 95
    1414//
    1515
     
    4242typedef unsigned long long __cfaabi_abi_exception_type_t;
    4343
     44#include <limits.h>                                                                             // CHAR_BIT
    4445#include "../src/virtual.h"
    4546#include "../src/exception.h"
     
    5051// increment/decrement unification
    5152
    52 static inline forall( dtype T | { T& ?+=?( T&, one_t ); } )
    53 T& ++? ( T& x ) { return x += 1; }
     53static inline {
     54        forall( dtype DT | { DT & ?+=?( DT &, one_t ); } )
     55        DT & ++?( DT & x ) { return x += 1; }
    5456
    55 static inline forall( dtype T | sized(T) | { void ?{}( T&, T ); void ^?{}( T& ); T& ?+=?( T&, one_t ); } )
    56 T& ?++ ( T& x ) { T tmp = x; x += 1; return tmp; }
     57        forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?+=?( DT &, one_t ); } )
     58        DT & ?++( DT & x ) { DT tmp = x; x += 1; return tmp; }
    5759
    58 static inline forall( dtype T | { T& ?-=?( T&, one_t ); } )
    59 T& --? ( T& x ) { return x -= 1; }
     60        forall( dtype DT | { DT & ?-=?( DT &, one_t ); } )
     61        DT & --?( DT & x ) { return x -= 1; }
    6062
    61 static inline forall( dtype T | sized(T) | { void ?{}( T&, T ); void ^?{}( T& ); T& ?-=?( T&, one_t ); } )
    62 T& ?-- ( T& x ) { T tmp = x; x -= 1; return tmp; }
     63        forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?-=?( DT &, one_t ); } )
     64        DT & ?--( DT & x ) { DT tmp = x; x -= 1; return tmp; }
     65} // distribution
     66
     67// universal typed pointer constant
     68// Compiler issue: there is a problem with anonymous types that do not have a size.
     69static inline forall( dtype DT | sized(DT) ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    6370
    6471// exponentiation operator implementation
     
    7380} // extern "C"
    7481
    75 static inline float ?\?( float x, float y ) { return powf( x, y ); }
    76 static inline double ?\?( double x, double y ) { return pow( x, y ); }
    77 static inline long double ?\?( long double x, long double y ) { return powl( x, y ); }
    78 static inline float _Complex ?\?( float _Complex x, _Complex float y ) { return cpowf(x, y ); }
    79 static inline double _Complex ?\?( double _Complex x, _Complex double y ) { return cpow( x, y ); }
    80 static inline long double _Complex ?\?( long double _Complex x, _Complex long double y ) { return cpowl( x, y ); }
     82static inline {
     83        float ?\?( float x, float y ) { return powf( x, y ); }
     84        double ?\?( double x, double y ) { return pow( x, y ); }
     85        long double ?\?( long double x, long double y ) { return powl( x, y ); }
     86        float _Complex ?\?( float _Complex x, _Complex float y ) { return cpowf(x, y ); }
     87        double _Complex ?\?( double _Complex x, _Complex double y ) { return cpow( x, y ); }
     88        long double _Complex ?\?( long double _Complex x, _Complex long double y ) { return cpowl( x, y ); }
     89} // distribution
    8190
    82 static inline long int ?\?( long int ep, unsigned long int y ) { // disallow negative exponent
    83         if ( y == 0 ) return 1;                                                         // base case
    84         if ( ep == 2 ) return ep << (y - 1);                            // special case, positive shifting only
    85         typeof( ep ) op = 1;                                                            // accumulate odd product
    86         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    87                 if ( (y & 1) == 1 ) op *= ep;                                   // odd ?
    88                 ep *= ep;
    89         } // for
    90         return ep * op;
    91 } // ?\?
     91#define __CFA_BASE_COMP_1__() if ( ep == 1 ) return 1
     92#define __CFA_BASE_COMP_2__() if ( ep == 2 ) return ep << (y - 1)
     93#define __CFA_EXP_OVERFLOW__() if ( y >= sizeof(y) * CHAR_BIT ) return 0
    9294
    93 static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); } )
    94 T ?\?( T ep, unsigned long int y ) {
    95         if ( y == 0 ) return 1;
    96         T op = 1;
    97         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    98                 if ( (y & 1) == 1 ) op = op * ep;                               // odd ?
    99                 ep = ep * ep;
    100         } // for
    101         return ep * op;
    102 } // ?\?
     95#define __CFA_EXP__() \
     96        if ( y == 0 ) return 1;                                                         /* convention */ \
     97        __CFA_BASE_COMP_1__();                                                          /* base case */ \
     98        __CFA_BASE_COMP_2__();                                                          /* special case, positive shifting for integral types */ \
     99        __CFA_EXP_OVERFLOW__();                                                         /* immediate overflow, negative exponent > 2^size-1 */ \
     100        typeof(ep) op = 1;                                                                      /* accumulate odd product */ \
     101        for ( ; y > 1; y >>= 1 ) {                                                      /* squaring exponentiation, O(log2 y) */ \
     102                if ( (y & 1) == 1 ) op = op * ep;                               /* odd ? */ \
     103                ep = ep * ep; \
     104        } \
     105        return ep * op
    103106
    104 // unsigned computation may be faster and larger
    105 static inline unsigned long int ?\?( unsigned long int ep, unsigned long int y ) { // disallow negative exponent
    106         if ( y == 0 ) return 1;                                                         // base case
    107         if ( ep == 2 ) return ep << (y - 1);                            // special case, positive shifting only
    108         typeof( ep ) op = 1;                                                            // accumulate odd product
    109         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    110                 if ( (y & 1) == 1 ) op *= ep;                                   // odd ?
    111                 ep *= ep;
    112         } // for
    113         return ep * op;
    114 } // ?\?
     107static inline {
     108        long int ?\?( int ep, unsigned int y ) { __CFA_EXP__(); }
     109        long int ?\?( long int ep, unsigned long int y ) { __CFA_EXP__(); }
     110        // unsigned computation may be faster and larger
     111        unsigned long int ?\?( unsigned int ep, unsigned int y ) { __CFA_EXP__(); }
     112        unsigned long int ?\?( unsigned long int ep, unsigned long int y ) { __CFA_EXP__(); }
     113} // distribution
    115114
    116 static inline double ?\?( long int x, signed long int y ) {     // allow negative exponent
    117         if ( y >=  0 ) return (double)(x \ (unsigned long int)y);
    118         else return 1.0 / x \ (unsigned int)(-y);
    119 } // ?\?
     115#undef __CFA_BASE_COMP_1__
     116#undef __CFA_BASE_COMP_2__
     117#undef __CFA_EXP_OVERFLOW__
     118#define __CFA_BASE_COMP_1__()
     119#define __CFA_BASE_COMP_2__()
     120#define __CFA_EXP_OVERFLOW__()
    120121
    121 // FIXME (x \ (unsigned long int)y) relies on X ?\?(T, unsigned long) a function that is neither
    122 // defined, nor passed as an assertion parameter. Without user-defined conversions, cannot specify
    123 // X as a type that casts to double, yet it doesn't make sense to write functions with that type
    124 // signature where X is double.
     122static inline forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) {
     123        OT ?\?( OT ep, unsigned int y ) { __CFA_EXP__(); }
     124        OT ?\?( OT ep, unsigned long int y ) { __CFA_EXP__(); }
     125} // distribution
    125126
    126 // static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); double ?/?( double, T ); } )
    127 // double ?\?( T x, signed long int y ) {
    128 //     if ( y >=  0 ) return (double)(x \ (unsigned long int)y);
    129 //     else return 1.0 / x \ (unsigned long int)(-y);
    130 // } // ?\?
     127#undef __CFA_BASE_COMP_1__
     128#undef __CFA_BASE_COMP_2__
     129#undef __CFA_EXP_OVERFLOW__
    131130
    132 static inline long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
    133 static inline unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; }
    134 static inline int ?\=?( int & x, unsigned long int y ) { x = x \ y; return x; }
    135 static inline unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
     131static inline {
     132        long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
     133        unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; }
     134        int ?\=?( int & x, unsigned long int y ) { x = x \ y; return x; }
     135        unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
     136} // distribution
    136137
    137138// Local Variables: //
  • libcfa/prelude/extras.c

    r6a9d4b4 r933f32f  
    1 #include <stddef.h>                                     // size_t, ptrdiff_t
     1#include <stddef.h>                                     // size_t, ptrdiff_t, intptr_t, uintptr_t
    22#include <stdint.h>                                     // intX_t, uintX_t, where X is 8, 16, 32, 64
    33#include <uchar.h>                                      // char16_t, char32_t
  • libcfa/prelude/extras.regx

    r6a9d4b4 r933f32f  
    11typedef.* size_t;
    22typedef.* ptrdiff_t;
     3typedef.* intptr_t;
     4typedef.* uintptr_t;
    35typedef.* __int8_t;
    46typedef.* __int16_t;
  • libcfa/prelude/prelude-gen.cc

    r6a9d4b4 r933f32f  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// prelude-gen.cc --
     8//
     9// Author           : Rob Schluntz and Thierry Delisle
     10// Created On       : Sat Feb 16 08:44:58 2019
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Apr  2 17:18:24 2019
     13// Update Count     : 37
     14//
     15
    116#include <algorithm>
    217#include <array>
     
    1126        bool hasComparison;
    1227} basicTypes[] = {
    13         // { "char"                  , false, true , },
    14         // { "signed char"           , false, true , },
    15         // { "unsigned char"         , false, true , },
     28        { "char"                  , false, true , },
     29        { "signed char"           , false, true , },
     30        { "unsigned char"         , false, true , },
    1631        { "signed short"          , false, true , },
    1732        { "unsigned short"        , false, true , },
     
    3449#if defined(__i386__) || defined(__ia64__) || defined(__x86_64__)
    3550        { "__float80"             , true , true , },
    36         { "_Float128"             , true , true , },
     51        { "__float128"            , true , true , },
    3752#endif
    3853};
     
    103118        { "?!=?", false, "signed int", Normal, "" },
    104119        { "?=?", true, "", Normal, "" }, // void * LHS, zero_t RHS ???
    105         { "*?", false, "&", Normal, " | sized(DT)" }, // & ???
     120//      { "*?", false, "&", Normal, " | sized(DT)" }, // & ???
     121        { "*?", false, "&", Normal, "" }, // & ???
    106122
    107123        { "?-?", false, "ptrdiff_t", Normal, " | sized(DT)" },
     
    150166        cout << endl;
    151167
    152         cout << "signed int ?==?( zero_t, zero_t ),                                                     ?!=?( zero_t, zero_t );" << endl;
    153         cout << "signed int ?==?( one_t, one_t ),                                                       ?!=?( one_t, one_t );" << endl;
    154         cout << "signed int ?==?( _Bool, _Bool ),                                                       ?!=?( _Bool, _Bool );" << endl;
    155         cout << "signed int     !?( _Bool );" << endl;
     168        cout << "signed int ?==?( zero_t, zero_t ),     ?!=?( zero_t, zero_t );" << endl;
     169        cout << "signed int ?==?( one_t, one_t ),       ?!=?( one_t, one_t );" << endl;
     170        cout << "signed int ?==?( _Bool, _Bool ),       ?!=?( _Bool, _Bool );" << endl;
     171        cout << "signed int !?( _Bool );" << endl;
    156172
    157173        for (auto op : arithmeticOperators) {
     
    188204        cout << "// Arithmetic Constructors //" << endl;
    189205        cout << "/////////////////////////////" << endl;
     206        cout << endl;
     207
    190208        auto otype = [](const std::string & type, bool do_volatile = false) {
    191                 cout << "void \t?{} ( " << type << " & );" << endl;
    192                 cout << "void \t?{} ( " << type << " &, " << type << " );" << endl;
    193                 cout << type << " \t?=? ( " << type << " &, " << type << " )";
    194                 if( do_volatile ) {
    195                         cout << ", \t?=?( volatile " << type << " &, " << type << " )";
     209                cout << "void ?{} (" << type << " &);" << endl;
     210                cout << "void ?{} (" << type << " &, " << type << ");" << endl;
     211                cout << type << " ?=? (" << type << " &, " << type << ")";
     212                if ( do_volatile ) {
     213                        cout << ", ?=?(volatile " << type << " &, " << type << ")";
    196214                }
    197215                cout << ";" << endl;
    198                 cout << "void \t^?{}( " << type << " & );" << endl;
     216                cout << "void ^?{}( " << type << " & );" << endl;
    199217        };
    200218
    201219        otype("zero_t");
     220        cout << endl;
    202221        otype("one_t");
     222        cout << endl;
    203223        otype("_Bool", true);
    204         otype("char", true);
    205         otype("signed char", true);
    206         otype("unsigned char", true);
     224        cout << endl;
    207225
    208226        for (auto type : basicTypes) {
    209                 cout << "void  ?{}(" << type.name << " &);" << endl;
    210                 cout << "void  ?{}(" << type.name << " &, " << type.name << ");" << endl;
     227                cout << "void ?{}(" << type.name << " &);" << endl;
     228                cout << "void ?{}(" << type.name << " &, " << type.name << ");" << endl;
     229                cout << "void ?{}(" << type.name << " &, zero_t);" << endl;
     230                cout << "void ?{}(" << type.name << " &, one_t);" << endl;
    211231                cout << "void ^?{}(" << type.name << " &);" << endl;
    212232                cout << endl;
     
    217237        cout << "// Pointer Constructors //" << endl;
    218238        cout << "//////////////////////////" << endl;
    219         cout << "forall(ftype FT) void  ?{}( FT *&, FT * );" << endl;
    220         cout << "forall(ftype FT) void  ?{}( FT * volatile &, FT * );" << endl;
     239        cout << endl;
     240
     241        cout << "forall(ftype FT) void ?{}( FT *&, FT * );" << endl;
     242        cout << "forall(ftype FT) void ?{}( FT * volatile &, FT * );" << endl;
    221243
    222244        // generate qualifiers
     
    242264                for (auto cvq : qualifiersPair) {
    243265                        for (auto is_vol : { "        ", "volatile" }) {
    244                                 cout << "forall(dtype DT) void  ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
     266                                cout << "forall(dtype DT) void ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
    245267                        }
    246268                }
    247269                for (auto cvq : qualifiersSingle) {
    248270                        for (auto is_vol : { "        ", "volatile" }) {
    249                                 cout << "forall(dtype DT) void  ?{}(" << cvq << type << " * " << is_vol << " &);" << endl;
     271                                cout << "forall(dtype DT) void ?{}(" << cvq << type << " * " << is_vol << " &);" << endl;
    250272                        }
    251273                        for (auto is_vol : { "        ", "volatile" }) {
     
    269291        cout << "forall(ftype FT) FT *                  ?=?( FT *          &, zero_t );" << endl;
    270292        cout << "forall(ftype FT) FT *                  ?=?( FT * volatile &, zero_t );" << endl;
    271         cout << "forall( ftype FT ) void        ?{}( FT *          & );" << endl;
    272         cout << "forall( ftype FT ) void        ^?{}( FT *         & );" << endl;
     293        cout << "forall(ftype FT) void  ?{}( FT *          & );" << endl;
     294        cout << "forall(ftype FT) void  ^?{}( FT *         & );" << endl;
    273295        cout << endl;
    274296
     
    277299        cout << "///////////////////////" << endl;
    278300
    279         cout << "forall( ftype FT ) FT *                        ?=?( FT *&, FT * );" << endl;
    280         cout << "forall( ftype FT ) FT *                        ?=?( FT * volatile &, FT * );" << endl;
    281         cout << "forall( ftype FT ) int !?( FT * );" << endl;
    282         cout << "forall( ftype FT ) signed int ?==?( FT *, FT * );" << endl;
    283         cout << "forall( ftype FT ) signed int ?!=?( FT *, FT * );" << endl;
    284         cout << "forall( ftype FT ) FT &                 *?( FT * );" << endl;
    285 
     301        cout << "forall(ftype FT) FT *                  ?=?( FT *&, FT * );" << endl;
     302        cout << "forall(ftype FT) FT *                  ?=?( FT * volatile &, FT * );" << endl;
     303        cout << "forall(ftype FT) int !?( FT * );" << endl;
     304        cout << "forall(ftype FT) signed int ?==?( FT *, FT * );" << endl;
     305        cout << "forall(ftype FT) signed int ?!=?( FT *, FT * );" << endl;
     306        cout << "forall(ftype FT) FT &           *?( FT * );" << endl;
    286307
    287308        for (auto op : pointerOperators) {
     
    387408}
    388409
     410// Local Variables: //
     411// tab-width: 4 //
     412// End: //
  • libcfa/prelude/sync-builtins.cf

    r6a9d4b4 r933f32f  
    323323_Bool __sync_bool_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    324324#endif
     325forall(dtype T) _Bool __sync_bool_compare_and_swap(T * volatile *, T *, T*, ...);
    325326
    326327char __sync_val_compare_and_swap(volatile char *, char, char,...);
     
    348349unsigned __int128 __sync_val_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    349350#endif
     351forall(dtype T) T * __sync_val_compare_and_swap(T * volatile *, T *, T*,...);
    350352
    351353char __sync_lock_test_and_set(volatile char *, char,...);
     
    434436#endif
    435437
    436 char __atomic_exchange_n(volatile char *, volatile char *, int);
     438char __atomic_exchange_n(volatile char *, char, int);
    437439char __atomic_exchange_1(volatile char *, char, int);
    438440void __atomic_exchange(volatile char *, volatile char *, volatile char *, int);
    439 signed char __atomic_exchange_n(volatile signed char *, volatile signed char *, int);
     441signed char __atomic_exchange_n(volatile signed char *, signed char, int);
    440442signed char __atomic_exchange_1(volatile signed char *, signed char, int);
    441443void __atomic_exchange(volatile signed char *, volatile signed char *, volatile signed char *, int);
    442 unsigned char __atomic_exchange_n(volatile unsigned char *, volatile unsigned char *, int);
     444unsigned char __atomic_exchange_n(volatile unsigned char *, unsigned char, int);
    443445unsigned char __atomic_exchange_1(volatile unsigned char *, unsigned char, int);
    444446void __atomic_exchange(volatile unsigned char *, volatile unsigned char *, volatile unsigned char *, int);
    445 signed short __atomic_exchange_n(volatile signed short *, volatile signed short *, int);
     447signed short __atomic_exchange_n(volatile signed short *, signed short, int);
    446448signed short __atomic_exchange_2(volatile signed short *, signed short, int);
    447449void __atomic_exchange(volatile signed short *, volatile signed short *, volatile signed short *, int);
    448 unsigned short __atomic_exchange_n(volatile unsigned short *, volatile unsigned short *, int);
     450unsigned short __atomic_exchange_n(volatile unsigned short *, unsigned short, int);
    449451unsigned short __atomic_exchange_2(volatile unsigned short *, unsigned short, int);
    450452void __atomic_exchange(volatile unsigned short *, volatile unsigned short *, volatile unsigned short *, int);
    451 signed int __atomic_exchange_n(volatile signed int *, volatile signed int *, int);
     453signed int __atomic_exchange_n(volatile signed int *, signed int, int);
    452454signed int __atomic_exchange_4(volatile signed int *, signed int, int);
    453455void __atomic_exchange(volatile signed int *, volatile signed int *, volatile signed int *, int);
    454 unsigned int __atomic_exchange_n(volatile unsigned int *, volatile unsigned int *, int);
     456unsigned int __atomic_exchange_n(volatile unsigned int *, unsigned int, int);
    455457unsigned int __atomic_exchange_4(volatile unsigned int *, unsigned int, int);
    456458void __atomic_exchange(volatile unsigned int *, volatile unsigned int *, volatile unsigned int *, int);
    457 signed long long int __atomic_exchange_n(volatile signed long long int *, volatile signed long long int *, int);
     459signed long long int __atomic_exchange_n(volatile signed long long int *, signed long long int, int);
    458460signed long long int __atomic_exchange_8(volatile signed long long int *, signed long long int, int);
    459461void __atomic_exchange(volatile signed long long int *, volatile signed long long int *, volatile signed long long int *, int);
    460 unsigned long long int __atomic_exchange_n(volatile unsigned long long int *, volatile unsigned long long int *, int);
     462unsigned long long int __atomic_exchange_n(volatile unsigned long long int *, unsigned long long int, int);
    461463unsigned long long int __atomic_exchange_8(volatile unsigned long long int *, unsigned long long int, int);
    462464void __atomic_exchange(volatile unsigned long long int *, volatile unsigned long long int *, volatile unsigned long long int *, int);
    463465#if defined(__SIZEOF_INT128__)
    464 signed __int128 __atomic_exchange_n(volatile signed __int128 *, volatile signed __int128 *, int);
     466signed __int128 __atomic_exchange_n(volatile signed __int128 *, signed __int128, int);
    465467signed __int128 __atomic_exchange_16(volatile signed __int128 *, signed __int128, int);
    466468void __atomic_exchange(volatile signed __int128 *, volatile signed __int128 *, volatile signed __int128 *, int);
    467 unsigned __int128 __atomic_exchange_n(volatile unsigned __int128 *, volatile unsigned __int128 *, int);
     469unsigned __int128 __atomic_exchange_n(volatile unsigned __int128 *, unsigned __int128, int);
    468470unsigned __int128 __atomic_exchange_16(volatile unsigned __int128 *, unsigned __int128, int);
    469471void __atomic_exchange(volatile unsigned __int128 *, volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    470472#endif
     473forall(dtype T) T * __atomic_exchange_n(T * volatile *, T *, int);
     474forall(dtype T) void __atomic_exchange(T * volatile *, T * volatile *, T * volatile *, int);
    471475
    472476_Bool __atomic_load_n(const volatile _Bool *, int);
     
    507511void __atomic_load(const volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    508512#endif
     513forall(dtype T) T * __atomic_load_n(T * const volatile *, int);
     514forall(dtype T) void __atomic_load(T * const volatile *, T **, int);
    509515
    510516_Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int);
     
    543549_Bool __atomic_compare_exchange   (volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128 *, _Bool, int, int);
    544550#endif
     551forall(dtype T) _Bool __atomic_compare_exchange_n (T * volatile *, T **, T*, _Bool, int, int);
     552forall(dtype T) _Bool __atomic_compare_exchange   (T * volatile *, T **, T**, _Bool, int, int);
    545553
    546554void __atomic_store_n(volatile _Bool *, _Bool, int);
     
    581589void __atomic_store(volatile unsigned __int128 *, unsigned __int128 *, int);
    582590#endif
     591forall(dtype T) void __atomic_store_n(T * volatile *, T *, int);
     592forall(dtype T) void __atomic_store(T * volatile *, T **, int);
    583593
    584594char __atomic_add_fetch  (volatile char *, char, int);
  • libcfa/src/Makefile.am

    r6a9d4b4 r933f32f  
    7474
    7575prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    76         ${AM_V_GEN}@CFACC@ ${AM_CFLAGS} ${CFLAGS} -quiet -in-tree @CONFIG_CFAFLAGS@ -XCFA -l ${<} -c -o ${@}
     76        ${AM_V_GEN}$(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    7777
    7878prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    7979        ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
    80         @CFACC@ ${AM_CFLAGS} ${CFLAGS} -quiet -in-tree @CONFIG_CFAFLAGS@ -XCFA -l ${<} -c -o ${@}
     80        $(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    8181
    8282
  • libcfa/src/Makefile.in

    r6a9d4b4 r933f32f  
    926926
    927927prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    928         ${AM_V_GEN}@CFACC@ ${AM_CFLAGS} ${CFLAGS} -quiet -in-tree @CONFIG_CFAFLAGS@ -XCFA -l ${<} -c -o ${@}
     928        ${AM_V_GEN}$(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    929929
    930930prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    931931        ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
    932         @CFACC@ ${AM_CFLAGS} ${CFLAGS} -quiet -in-tree @CONFIG_CFAFLAGS@ -XCFA -l ${<} -c -o ${@}
     932        $(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    933933
    934934#----------------------------------------------------------------------------------------------------------------
  • libcfa/src/bits/containers.hfa

    r6a9d4b4 r933f32f  
    186186
    187187        forall(dtype T | is_node(T))
    188         static inline bool ?!=?( __queue(T) & this, zero_t zero ) {
     188        static inline bool ?!=?( __queue(T) & this, __attribute__((unused)) zero_t zero ) {
    189189                return this.head != 0;
    190190        }
     
    196196//-----------------------------------------------------------------------------
    197197#ifdef __cforall
    198         forall(dtype TYPE | sized(TYPE))
     198        forall(dtype TYPE)
    199199        #define T TYPE
    200200        #define __getter_t * [T * & next, T * & prev] ( T & )
     
    268268
    269269        forall(dtype T | sized(T))
    270         static inline bool ?!=?( __dllist(T) & this, zero_t zero ) {
     270        static inline bool ?!=?( __dllist(T) & this, __attribute__((unused)) zero_t zero ) {
    271271                return this.head != 0;
    272272        }
  • libcfa/src/concurrency/CtxSwitch-i386.S

    r6a9d4b4 r933f32f  
    4141#define PC_OFFSET       ( 2 * PTR_BYTE )
    4242
    43 .text
     43        .text
    4444        .align 2
    45 .globl  CtxSwitch
     45        .globl CtxSwitch
     46        .type  CtxSwitch, @function
    4647CtxSwitch:
    4748
     
    5051
    5152        movl 4(%esp),%eax
    52 
    53         // Save floating & SSE control words on the stack.
    54 
    55         sub    $8,%esp
    56         stmxcsr 0(%esp)         // 4 bytes
    57         fnstcw  4(%esp)         // 2 bytes
    5853
    5954        // Save volatile registers on the stack.
     
    6762        movl %esp,SP_OFFSET(%eax)
    6863        movl %ebp,FP_OFFSET(%eax)
    69 //      movl 4(%ebp),%ebx       // save previous eip for debugger
    70 //      movl %ebx,PC_OFFSET(%eax)
    7164
    7265        // Copy the "to" context argument from the stack to register eax
     
    7467        // argument is now at 8 + 12 = 20(%esp)
    7568
    76         movl 28(%esp),%eax
     69        movl 20(%esp),%eax
    7770
    7871        // Load new context from the "to" area.
     
    8780        popl %ebx
    8881
    89         // Load floating & SSE control words from the stack.
    90 
    91         fldcw   4(%esp)
    92         ldmxcsr 0(%esp)
    93         add    $8,%esp
    94 
    9582        // Return to thread.
    9683
    9784        ret
     85        .size  CtxSwitch, .-CtxSwitch
    9886
    9987// Local Variables: //
  • libcfa/src/concurrency/CtxSwitch-x86_64.S

    r6a9d4b4 r933f32f  
    3939#define SP_OFFSET       ( 0 * PTR_BYTE )
    4040#define FP_OFFSET       ( 1 * PTR_BYTE )
    41 #define PC_OFFSET       ( 2 * PTR_BYTE )
    4241
    43 .text
     42//-----------------------------------------------------------------------------
     43// Regular context switch routine which enables switching from one context to anouther
     44        .text
    4445        .align 2
    45 .globl  CtxSwitch
     46        .globl CtxSwitch
     47        .type  CtxSwitch, @function
    4648CtxSwitch:
    47 
    48         // Save floating & SSE control words on the stack.
    49 
    50         subq   $8,%rsp
    51         stmxcsr 0(%rsp)         // 4 bytes
    52         fnstcw  4(%rsp)         // 2 bytes
    5349
    5450        // Save volatile registers on the stack.
     
    7874        popq %r15
    7975
    80         // Load floating & SSE control words from the stack.
    81 
    82         fldcw   4(%rsp)
    83         ldmxcsr 0(%rsp)
    84         addq   $8,%rsp
    85 
    8676        // Return to thread.
    8777
    8878        ret
     79        .size  CtxSwitch, .-CtxSwitch
    8980
    90 .text
     81//-----------------------------------------------------------------------------
     82// Stub used to create new stacks which are ready to be context switched to
     83        .text
    9184        .align 2
    92 .globl  CtxInvokeStub
     85        .globl CtxInvokeStub
     86        .type    CtxInvokeStub, @function
    9387CtxInvokeStub:
    9488        movq %rbx, %rdi
    9589        jmp *%r12
     90        .size  CtxInvokeStub, .-CtxInvokeStub
    9691
    9792// Local Variables: //
  • libcfa/src/concurrency/coroutine.cfa

    r6a9d4b4 r933f32f  
    3535
    3636extern "C" {
    37       void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) __attribute__ ((__noreturn__));
    38       static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
    39       static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
    40             abort();
    41       }
     37        void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     38        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
     39        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
     40                abort();
     41        }
     42
     43        extern void CtxRet( struct __stack_context_t * to ) asm ("CtxRet") __attribute__ ((__noreturn__));
    4244}
    4345
     
    4749// minimum feasible stack size in bytes
    4850#define MinStackSize 1000
    49 static size_t pageSize = 0;                             // architecture pagesize HACK, should go in proper runtime singleton
     51extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
     52
     53void __stack_prepare( __stack_info_t * this, size_t create_size );
    5054
    5155//-----------------------------------------------------------------------------
    5256// Coroutine ctors and dtors
    53 void ?{}( coStack_t & this, void * storage, size_t storageSize ) with( this ) {
    54       size               = storageSize == 0 ? 65000 : storageSize; // size of stack
    55       this.storage = storage;                                // pointer to stack
    56       limit              = NULL;                                   // stack grows towards stack limit
    57       base               = NULL;                                   // base of stack
    58       context    = NULL;                                   // address of cfa_context_t
    59       top                = NULL;                                   // address of top of storage
    60       userStack  = storage != NULL;
    61 }
    62 
    63 void ^?{}(coStack_t & this) {
    64       if ( ! this.userStack && this.storage ) {
    65             __cfaabi_dbg_debug_do(
    66                   if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
    67                         abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    68                   }
    69             );
    70             free( this.storage );
    71       }
     57void ?{}( __stack_info_t & this, void * storage, size_t storageSize ) {
     58        this.storage   = (__stack_t *)storage;
     59
     60        // Did we get a piece of storage ?
     61        if (this.storage || storageSize != 0) {
     62                // We either got a piece of storage or the user asked for a specific size
     63                // Immediately create the stack
     64                // (This is slightly unintuitive that non-default sized coroutines create are eagerly created
     65                // but it avoids that all coroutines carry an unnecessary size)
     66                verify( storageSize != 0 );
     67                __stack_prepare( &this, storageSize );
     68        }
     69}
     70
     71void ^?{}(__stack_info_t & this) {
     72        bool userStack = ((intptr_t)this.storage & 0x1) != 0;
     73        if ( ! userStack && this.storage ) {
     74                __attribute__((may_alias)) intptr_t * istorage = (intptr_t *)&this.storage;
     75                *istorage &= (intptr_t)-1;
     76
     77                void * storage = this.storage->limit;
     78                __cfaabi_dbg_debug_do(
     79                        storage = (char*)(storage) - __page_size;
     80                        if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) {
     81                                abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
     82                        }
     83                );
     84                __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
     85                free( storage );
     86        }
    7287}
    7388
    7489void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
    75       (this.stack){storage, storageSize};
    76       this.name = name;
    77       errno_ = 0;
    78       state = Start;
    79       starter = NULL;
    80       last = NULL;
    81       cancellation = NULL;
     90        (this.context){NULL, NULL};
     91        (this.stack){storage, storageSize};
     92        this.name = name;
     93        state = Start;
     94        starter = NULL;
     95        last = NULL;
     96        cancellation = NULL;
    8297}
    8398
    8499void ^?{}(coroutine_desc& this) {
    85       if(this.state != Halted && this.state != Start) {
    86             coroutine_desc * src = TL_GET( this_coroutine );
    87             coroutine_desc * dst = &this;
    88 
    89             struct _Unwind_Exception storage;
    90             storage.exception_class = -1;
    91             storage.exception_cleanup = _CtxCoroutine_UnwindCleanup;
    92             this.cancellation = &storage;
    93             this.last = src;
    94 
    95               // not resuming self ?
    96               if ( src == dst ) {
    97                       abort( "Attempt by coroutine %.256s (%p) to terminate itself.\n", src->name, src );
    98             }
    99 
    100               CoroutineCtxSwitch( src, dst );
    101       }
     100        if(this.state != Halted && this.state != Start) {
     101                coroutine_desc * src = TL_GET( this_thread )->curr_cor;
     102                coroutine_desc * dst = &this;
     103
     104                struct _Unwind_Exception storage;
     105                storage.exception_class = -1;
     106                storage.exception_cleanup = _CtxCoroutine_UnwindCleanup;
     107                this.cancellation = &storage;
     108                this.last = src;
     109
     110                // not resuming self ?
     111                if ( src == dst ) {
     112                        abort( "Attempt by coroutine %.256s (%p) to terminate itself.\n", src->name, src );
     113                }
     114
     115                CoroutineCtxSwitch( src, dst );
     116        }
    102117}
    103118
     
    106121forall(dtype T | is_coroutine(T))
    107122void prime(T& cor) {
    108       coroutine_desc* this = get_coroutine(cor);
    109       assert(this->state == Start);
    110 
    111       this->state = Primed;
    112       resume(cor);
    113 }
    114 
    115 // Wrapper for co
    116 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    117       // Safety note : This could cause some false positives due to preemption
    118       verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
    119       disable_interrupts();
    120 
    121       // set state of current coroutine to inactive
    122       src->state = src->state == Halted ? Halted : Inactive;
    123 
    124       // set new coroutine that task is executing
    125       kernelTLS.this_coroutine = dst;
    126 
    127       // context switch to specified coroutine
    128       assert( src->stack.context );
    129       CtxSwitch( src->stack.context, dst->stack.context );
    130       // when CtxSwitch returns we are back in the src coroutine
    131 
    132       // set state of new coroutine to active
    133       src->state = Active;
    134 
    135       enable_interrupts( __cfaabi_dbg_ctx );
    136       // Safety note : This could cause some false positives due to preemption
    137       verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
    138 
    139       if( unlikely(src->cancellation != NULL) ) {
    140             _CtxCoroutine_Unwind(src->cancellation);
    141       }
    142 } //ctxSwitchDirect
    143 
    144 void create_stack( coStack_t* this, unsigned int storageSize ) with( *this ) {
    145       //TEMP HACK do this on proper kernel startup
    146       if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
    147 
    148       size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
    149 
    150       if ( !storage ) {
    151             __cfaabi_dbg_print_safe("Kernel : Creating stack of size %zu for stack obj %p\n", cxtSize + size + 8, this);
    152 
    153             userStack = false;
    154             size = libCeiling( storageSize, 16 );
    155             // use malloc/memalign because "new" raises an exception for out-of-memory
    156 
    157             // assume malloc has 8 byte alignment so add 8 to allow rounding up to 16 byte alignment
    158             __cfaabi_dbg_debug_do( storage = memalign( pageSize, cxtSize + size + pageSize ) );
    159             __cfaabi_dbg_no_debug_do( storage = malloc( cxtSize + size + 8 ) );
    160 
    161             __cfaabi_dbg_debug_do(
    162                   if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) {
    163                         abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
    164                   } // if
    165             );
    166 
    167             if ( (intptr_t)storage == 0 ) {
    168                   abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
    169             } // if
    170 
    171             __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
    172             __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
    173 
    174       } else {
    175             __cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%u bytes)\n", this, storage, storageSize);
    176 
    177             assertf( ((size_t)storage & (libAlign() - 1)) == 0ul, "Stack storage %p for task/coroutine must be aligned on %d byte boundary.", storage, (int)libAlign() );
    178             userStack = true;
    179             size = storageSize - cxtSize;
    180 
    181             if ( size % 16 != 0u ) size -= 8;
    182 
    183             limit = (char *)libCeiling( (unsigned long)storage, 16 ); // minimum alignment
    184       } // if
    185       assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
    186 
    187       base = (char *)limit + size;
    188       context = base;
    189       top = (char *)context + cxtSize;
     123        coroutine_desc* this = get_coroutine(cor);
     124        assert(this->state == Start);
     125
     126        this->state = Primed;
     127        resume(cor);
     128}
     129
     130[void *, size_t] __stack_alloc( size_t storageSize ) {
     131        static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     132        assert(__page_size != 0l);
     133        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
     134
     135        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
     136        void * storage;
     137        __cfaabi_dbg_debug_do(
     138                storage = memalign( __page_size, size + __page_size );
     139        );
     140        __cfaabi_dbg_no_debug_do(
     141                storage = (void*)malloc(size);
     142        );
     143
     144        __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size);
     145        __cfaabi_dbg_debug_do(
     146                if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     147                        abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
     148                }
     149                storage = (void *)(((intptr_t)storage) + __page_size);
     150        );
     151
     152        verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul );
     153        return [storage, size];
     154}
     155
     156void __stack_prepare( __stack_info_t * this, size_t create_size ) {
     157        static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     158        bool userStack;
     159        void * storage;
     160        size_t size;
     161        if ( !this->storage ) {
     162                userStack = false;
     163                [storage, size] = __stack_alloc( create_size );
     164        } else {
     165                userStack = true;
     166                __cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%zd bytes)\n", this, this->storage, (intptr_t)this->storage->limit - (intptr_t)this->storage->base);
     167
     168                // The stack must be aligned, advance the pointer to the next align data
     169                storage = (void*)libCeiling( (intptr_t)this->storage, libAlign());
     170
     171                // The size needs to be shrinked to fit all the extra data structure and be aligned
     172                ptrdiff_t diff = (intptr_t)storage - (intptr_t)this->storage;
     173                size = libFloor(create_size - stack_data_size - diff, libAlign());
     174        } // if
     175        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
     176
     177        this->storage = (__stack_t *)((intptr_t)storage + size);
     178        this->storage->limit = storage;
     179        this->storage->base  = (void*)((intptr_t)storage + size);
     180        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage;
     181        *istorage |= userStack ? 0x1 : 0x0;
    190182}
    191183
     
    193185// is not inline (We can't inline Cforall in C)
    194186extern "C" {
    195       void __suspend_internal(void) {
    196             suspend();
    197       }
    198 
    199       void __leave_coroutine() {
    200             coroutine_desc * src = TL_GET( this_coroutine ); // optimization
    201             coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
    202 
    203             src->state = Halted;
    204 
    205             assertf( starter != 0,
    206                   "Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
    207                   "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    208                   src->name, src );
    209             assertf( starter->state != Halted,
    210                   "Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
    211                   "Possible cause is terminated coroutine's main routine has already returned.",
    212                   src->name, src, starter->name, starter );
    213 
    214             CoroutineCtxSwitch( src, starter );
    215       }
     187        void __suspend_internal(void) {
     188                suspend();
     189        }
     190
     191        void __leave_coroutine( coroutine_desc * src ) {
     192                coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
     193
     194                src->state = Halted;
     195
     196                assertf( starter != 0,
     197                        "Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
     198                        "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
     199                        src->name, src );
     200                assertf( starter->state != Halted,
     201                        "Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
     202                        "Possible cause is terminated coroutine's main routine has already returned.",
     203                        src->name, src, starter->name, starter );
     204
     205                CoroutineCtxSwitch( src, starter );
     206        }
    216207}
    217208
  • libcfa/src/concurrency/coroutine.hfa

    r6a9d4b4 r933f32f  
    4646//-----------------------------------------------------------------------------
    4747// Public coroutine API
    48 static inline void suspend();
     48static inline void suspend(void);
    4949
    5050forall(dtype T | is_coroutine(T))
    51 static inline void resume(T & cor);
     51static inline T & resume(T & cor);
    5252
    5353forall(dtype T | is_coroutine(T))
     
    6464      forall(dtype T | is_coroutine(T))
    6565      void CtxStart(T * this, void ( *invoke)(T *));
     66
     67        extern void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     68
     69        extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
    6670}
    6771
    6872// Private wrappers for context switch and stack creation
    69 extern void CoroutineCtxSwitch(coroutine_desc * src, coroutine_desc * dst);
    70 extern void create_stack( coStack_t * this, unsigned int storageSize );
     73// Wrapper for co
     74static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
     75        // set state of current coroutine to inactive
     76        src->state = src->state == Halted ? Halted : Inactive;
     77
     78        // set new coroutine that task is executing
     79        TL_GET( this_thread )->curr_cor = dst;
     80
     81        // context switch to specified coroutine
     82        verify( dst->context.SP );
     83        CtxSwitch( &src->context, &dst->context );
     84        // when CtxSwitch returns we are back in the src coroutine
     85
     86        // set state of new coroutine to active
     87        src->state = Active;
     88
     89        if( unlikely(src->cancellation != NULL) ) {
     90                _CtxCoroutine_Unwind(src->cancellation, src);
     91        }
     92}
     93
     94extern void __stack_prepare   ( __stack_info_t * this, size_t size /* ignored if storage already allocated */);
    7195
    7296// Suspend implementation inlined for performance
    73 static inline void suspend() {
     97static inline void suspend(void) {
    7498        // optimization : read TLS once and reuse it
    7599        // Safety note: this is preemption safe since if
     
    77101        // will also migrate which means this value will
    78102        // stay in syn with the TLS
    79         coroutine_desc * src = TL_GET( this_coroutine );
     103        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    80104
    81105        assertf( src->last != 0,
     
    93117// Resume implementation inlined for performance
    94118forall(dtype T | is_coroutine(T))
    95 static inline void resume(T & cor) {
     119static inline T & resume(T & cor) {
    96120        // optimization : read TLS once and reuse it
    97121        // Safety note: this is preemption safe since if
     
    99123        // will also migrate which means this value will
    100124        // stay in syn with the TLS
    101         coroutine_desc * src = TL_GET( this_coroutine );
     125        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    102126        coroutine_desc * dst = get_coroutine(cor);
    103127
    104         if( unlikely(!dst->stack.base) ) {
    105                 create_stack(&dst->stack, dst->stack.size);
     128        if( unlikely(dst->context.SP == NULL) ) {
     129                __stack_prepare(&dst->stack, 65000);
    106130                CtxStart(&cor, CtxInvokeCoroutine);
    107131        }
     
    121145        // always done for performance testing
    122146        CoroutineCtxSwitch( src, dst );
     147
     148        return cor;
    123149}
    124150
     
    129155        // will also migrate which means this value will
    130156        // stay in syn with the TLS
    131         coroutine_desc * src = TL_GET( this_coroutine );
     157        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    132158
    133159        // not resuming self ?
  • libcfa/src/concurrency/invoke.c

    r6a9d4b4 r933f32f  
    2828
    2929extern void __suspend_internal(void);
    30 extern void __leave_coroutine(void);
    31 extern void __finish_creation(void);
     30extern void __leave_coroutine( struct coroutine_desc * );
     31extern void __finish_creation( struct thread_desc * );
    3232extern void __leave_thread_monitor( struct thread_desc * this );
    3333extern void disable_interrupts();
     
    4747        cor->state = Active;
    4848
    49         enable_interrupts( __cfaabi_dbg_ctx );
    50 
    5149        main( this );
    5250
    5351        //Final suspend, should never return
    54         __leave_coroutine();
     52        __leave_coroutine( cor );
    5553        __cabi_abort( "Resumed dead coroutine" );
    5654}
     
    6260        __attribute((__unused__)) struct _Unwind_Exception * unwind_exception,
    6361        __attribute((__unused__)) struct _Unwind_Context * context,
    64         __attribute((__unused__)) void * param
     62        void * param
    6563) {
    6664        if( actions & _UA_END_OF_STACK  ) {
    6765                // We finished unwinding the coroutine,
    6866                // leave it
    69                 __leave_coroutine();
     67                __leave_coroutine( param );
    7068                __cabi_abort( "Resumed dead coroutine" );
    7169        }
     
    7573}
    7674
    77 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) __attribute__ ((__noreturn__));
    78 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage) {
    79         _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, NULL );
     75void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) __attribute__ ((__noreturn__));
     76void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) {
     77        _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, cor );
    8078        printf("UNWIND ERROR %d after force unwind\n", ret);
    8179        abort();
     
    8886        void *this
    8987) {
     88        // Fetch the thread handle from the user defined thread structure
     89        struct thread_desc* thrd = get_thread( this );
     90
    9091        // First suspend, once the thread arrives here,
    9192        // the function pointer to main can be invalidated without risk
    92         __finish_creation();
    93 
    94         // Fetch the thread handle from the user defined thread structure
    95         struct thread_desc* thrd = get_thread( this );
    96         thrd->self_cor.last = NULL;
     93        __finish_creation( thrd );
    9794
    9895        // Officially start the thread by enabling preemption
     
    120117        void (*invoke)(void *)
    121118) {
    122         struct coStack_t* stack = &get_coroutine( this )->stack;
     119        struct coroutine_desc * cor = get_coroutine( this );
     120        struct __stack_t * stack = cor->stack.storage;
    123121
    124122#if defined( __i386 )
    125123
    126124        struct FakeStack {
    127             void *fixedRegisters[3];                    // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)
    128             uint32_t mxcr;                        // SSE Status and Control bits (control bits are preserved across function calls)
    129             uint16_t fcw;                         // X97 FPU control word (preserved across function calls)
     125            void *fixedRegisters[3];              // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)
    130126            void *rturn;                          // where to go on return from uSwitch
    131             void *dummyReturn;                          // fake return compiler would have pushed on call to uInvoke
    132             void *argument[3];                          // for 16-byte ABI, 16-byte alignment starts here
    133             void *padding;                              // padding to force 16-byte alignment, as "base" is 16-byte aligned
     127            void *dummyReturn;                    // fake return compiler would have pushed on call to uInvoke
     128            void *argument[3];                    // for 16-byte ABI, 16-byte alignment starts here
     129            void *padding;                        // padding to force 16-byte alignment, as "base" is 16-byte aligned
    134130        };
    135131
    136         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    137         ((struct machine_context_t *)stack->context)->FP = NULL;                // terminate stack with NULL fp
     132        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     133        cor->context.FP = NULL;         // terminate stack with NULL fp
    138134
    139         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    140         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[0] = this;     // argument to invoke
    141         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke;
    142         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    143         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
     135        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
     136
     137        fs->dummyReturn = NULL;
     138        fs->argument[0] = this;     // argument to invoke
     139        fs->rturn = invoke;
    144140
    145141#elif defined( __x86_64 )
     
    147143        struct FakeStack {
    148144                void *fixedRegisters[5];            // fixed registers rbx, r12, r13, r14, r15
    149                 uint32_t mxcr;                      // SSE Status and Control bits (control bits are preserved across function calls)
    150                 uint16_t fcw;                       // X97 FPU control word (preserved across function calls)
    151145                void *rturn;                        // where to go on return from uSwitch
    152146                void *dummyReturn;                  // NULL return address to provide proper alignment
    153147        };
    154148
    155         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    156         ((struct machine_context_t *)stack->context)->FP = NULL;                // terminate stack with NULL fp
     149        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     150        cor->context.FP = NULL;         // terminate stack with NULL fp
    157151
    158         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    159         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = CtxInvokeStub;
    160         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = this;
    161         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke;
    162         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    163         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
     152        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
     153
     154        fs->dummyReturn = NULL;
     155        fs->rturn = CtxInvokeStub;
     156        fs->fixedRegisters[0] = this;
     157        fs->fixedRegisters[1] = invoke;
    164158
    165159#elif defined( __ARM_ARCH )
     
    171165        };
    172166
    173         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    174         ((struct machine_context_t *)stack->context)->FP = NULL;
     167        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     168        cor->context.FP = NULL;
    175169
    176         struct FakeStack *fs = (struct FakeStack *)((struct machine_context_t *)stack->context)->SP;
     170        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
    177171
    178172        fs->intRegs[8] = CtxInvokeStub;
  • libcfa/src/concurrency/invoke.h

    r6a9d4b4 r933f32f  
    5050
    5151                extern thread_local struct KernelThreadData {
    52                         struct coroutine_desc * volatile this_coroutine;
    5352                        struct thread_desc    * volatile this_thread;
    5453                        struct processor      * volatile this_processor;
     
    6160                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    6261        }
    63 
    64         static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); }
    65         static inline struct thread_desc    * volatile active_thread   () { return TL_GET( this_thread    ); }
    66         static inline struct processor      * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE
    6762        #endif
    6863
    69         struct coStack_t {
    70                 size_t size;                                                                    // size of stack
    71                 void * storage;                                                                 // pointer to stack
    72                 void * limit;                                                                   // stack grows towards stack limit
    73                 void * base;                                                                    // base of stack
    74                 void * context;                                                                 // address of cfa_context_t
    75                 void * top;                                                                             // address of top of storage
    76                 bool userStack;                                                                 // whether or not the user allocated the stack
     64        struct __stack_context_t {
     65                void * SP;
     66                void * FP;
     67        };
     68
     69        // low adresses  :           +----------------------+ <- start of allocation
     70        //                           |  optional guard page |
     71        //                           +----------------------+ <- __stack_t.limit
     72        //                           |                      |
     73        //                           |       /\ /\ /\       |
     74        //                           |       || || ||       |
     75        //                           |                      |
     76        //                           |    program  stack    |
     77        //                           |                      |
     78        // __stack_info_t.storage -> +----------------------+ <- __stack_t.base
     79        //                           |      __stack_t       |
     80        // high adresses :           +----------------------+ <- end of allocation
     81
     82        struct __stack_t {
     83                // stack grows towards stack limit
     84                void * limit;
     85
     86                // base of stack
     87                void * base;
     88        };
     89
     90        struct __stack_info_t {
     91                // pointer to stack
     92                struct __stack_t * storage;
    7793        };
    7894
     
    8096
    8197        struct coroutine_desc {
     98                // context that is switch during a CtxSwitch
     99                struct __stack_context_t context;
     100
    82101                // stack information of the coroutine
    83                 struct coStack_t stack;
    84 
    85                 // textual name for coroutine/task, initialized by uC++ generated code
     102                struct __stack_info_t stack;
     103
     104                // textual name for coroutine/task
    86105                const char * name;
    87 
    88                 // copy of global UNIX variable errno
    89                 int errno_;
    90106
    91107                // current execution status for coroutine
    92108                enum coroutine_state state;
     109
    93110                // first coroutine to resume this one
    94111                struct coroutine_desc * starter;
     
    144161        struct thread_desc {
    145162                // Core threading fields
     163                // context that is switch during a CtxSwitch
     164                struct __stack_context_t context;
     165
     166                // current execution status for coroutine
     167                enum coroutine_state state;
     168
     169                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
     170
    146171                // coroutine body used to store context
    147172                struct coroutine_desc  self_cor;
     
    170195                        struct thread_desc * prev;
    171196                } node;
    172      };
    173 
    174      #ifdef __cforall
    175      extern "Cforall" {
     197        };
     198
     199        #ifdef __cforall
     200        extern "Cforall" {
     201                static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
     202                static inline struct thread_desc    * active_thread   () { return TL_GET( this_thread    ); }
     203                static inline struct processor      * active_processor() { return TL_GET( this_processor ); } // UNSAFE
     204
    176205                static inline thread_desc * & get_next( thread_desc & this ) {
    177206                        return this.next;
     
    231260        // assembler routines that performs the context switch
    232261        extern void CtxInvokeStub( void );
    233         void CtxSwitch( void * from, void * to ) asm ("CtxSwitch");
    234 
    235         #if   defined( __i386 )
    236         #define CtxGet( ctx ) __asm__ ( \
    237                         "movl %%esp,%0\n"   \
    238                         "movl %%ebp,%1\n"   \
    239                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    240         #elif defined( __x86_64 )
    241         #define CtxGet( ctx ) __asm__ ( \
    242                         "movq %%rsp,%0\n"   \
    243                         "movq %%rbp,%1\n"   \
    244                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    245         #elif defined( __ARM_ARCH )
    246         #define CtxGet( ctx ) __asm__ ( \
    247                         "mov %0,%%sp\n"   \
    248                         "mov %1,%%r11\n"   \
    249                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    250         #else
    251                 #error unknown hardware architecture
    252         #endif
     262        extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
     263        // void CtxStore ( void * this ) asm ("CtxStore");
     264        // void CtxRet   ( void * dst  ) asm ("CtxRet");
    253265
    254266#endif //_INVOKE_PRIVATE_H_
  • libcfa/src/concurrency/kernel.cfa

    r6a9d4b4 r933f32f  
    3636#include "invoke.h"
    3737
     38//-----------------------------------------------------------------------------
     39// Some assembly required
     40#if   defined( __i386 )
     41        #define CtxGet( ctx )        \
     42                __asm__ volatile (     \
     43                        "movl %%esp,%0\n"\
     44                        "movl %%ebp,%1\n"\
     45                        : "=rm" (ctx.SP),\
     46                                "=rm" (ctx.FP) \
     47                )
     48
     49        // mxcr : SSE Status and Control bits (control bits are preserved across function calls)
     50        // fcw  : X87 FPU control word (preserved across function calls)
     51        #define __x87_store         \
     52                uint32_t __mxcr;      \
     53                uint16_t __fcw;       \
     54                __asm__ volatile (    \
     55                        "stmxcsr %0\n"  \
     56                        "fnstcw  %1\n"  \
     57                        : "=m" (__mxcr),\
     58                                "=m" (__fcw)  \
     59                )
     60
     61        #define __x87_load         \
     62                __asm__ volatile (   \
     63                        "fldcw  %1\n"  \
     64                        "ldmxcsr %0\n" \
     65                        ::"m" (__mxcr),\
     66                                "m" (__fcw)  \
     67                )
     68
     69#elif defined( __x86_64 )
     70        #define CtxGet( ctx )        \
     71                __asm__ volatile (     \
     72                        "movq %%rsp,%0\n"\
     73                        "movq %%rbp,%1\n"\
     74                        : "=rm" (ctx.SP),\
     75                                "=rm" (ctx.FP) \
     76                )
     77
     78        #define __x87_store         \
     79                uint32_t __mxcr;      \
     80                uint16_t __fcw;       \
     81                __asm__ volatile (    \
     82                        "stmxcsr %0\n"  \
     83                        "fnstcw  %1\n"  \
     84                        : "=m" (__mxcr),\
     85                                "=m" (__fcw)  \
     86                )
     87
     88        #define __x87_load          \
     89                __asm__ volatile (    \
     90                        "fldcw  %1\n"   \
     91                        "ldmxcsr %0\n"  \
     92                        :: "m" (__mxcr),\
     93                                "m" (__fcw)  \
     94                )
     95
     96
     97#elif defined( __ARM_ARCH )
     98#define CtxGet( ctx ) __asm__ ( \
     99                "mov %0,%%sp\n"   \
     100                "mov %1,%%r11\n"   \
     101        : "=rm" (ctx.SP), "=rm" (ctx.FP) )
     102#else
     103        #error unknown hardware architecture
     104#endif
     105
     106//-----------------------------------------------------------------------------
    38107//Start and stop routine for the kernel, declared first to make sure they run first
    39108static void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     
    42111//-----------------------------------------------------------------------------
    43112// Kernel storage
    44 KERNEL_STORAGE(cluster,           mainCluster);
    45 KERNEL_STORAGE(processor,         mainProcessor);
    46 KERNEL_STORAGE(thread_desc,       mainThread);
    47 KERNEL_STORAGE(machine_context_t, mainThreadCtx);
     113KERNEL_STORAGE(cluster,         mainCluster);
     114KERNEL_STORAGE(processor,       mainProcessor);
     115KERNEL_STORAGE(thread_desc,     mainThread);
     116KERNEL_STORAGE(__stack_t,       mainThreadCtx);
    48117
    49118cluster     * mainCluster;
     
    54123struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    55124}
     125
     126size_t __page_size = 0;
    56127
    57128//-----------------------------------------------------------------------------
     
    60131        NULL,
    61132        NULL,
    62         NULL,
    63133        { 1, false, false }
    64134};
     
    67137// Struct to steal stack
    68138struct current_stack_info_t {
    69         machine_context_t ctx;
    70         unsigned int size;              // size of stack
     139        __stack_t * storage;            // pointer to stack object
    71140        void *base;                             // base of stack
    72         void *storage;                  // pointer to stack
    73141        void *limit;                    // stack grows towards stack limit
    74142        void *context;                  // address of cfa_context_t
    75         void *top;                              // address of top of storage
    76143};
    77144
    78145void ?{}( current_stack_info_t & this ) {
    79         CtxGet( this.ctx );
    80         this.base = this.ctx.FP;
    81         this.storage = this.ctx.SP;
     146        __stack_context_t ctx;
     147        CtxGet( ctx );
     148        this.base = ctx.FP;
    82149
    83150        rlimit r;
    84151        getrlimit( RLIMIT_STACK, &r);
    85         this.size = r.rlim_cur;
    86 
    87         this.limit = (void *)(((intptr_t)this.base) - this.size);
     152        size_t size = r.rlim_cur;
     153
     154        this.limit = (void *)(((intptr_t)this.base) - size);
    88155        this.context = &storage_mainThreadCtx;
    89         this.top = this.base;
    90156}
    91157
    92158//-----------------------------------------------------------------------------
    93159// Main thread construction
    94 void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) {
    95         size      = info->size;
    96         storage   = info->storage;
    97         limit     = info->limit;
    98         base      = info->base;
    99         context   = info->context;
    100         top       = info->top;
    101         userStack = true;
    102 }
    103160
    104161void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
    105         stack{ info };
     162        stack.storage = info->storage;
     163        with(*stack.storage) {
     164                limit     = info->limit;
     165                base      = info->base;
     166        }
     167        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*) &stack.storage;
     168        *istorage |= 0x1;
    106169        name = "Main Thread";
    107         errno_ = 0;
    108170        state = Start;
    109171        starter = NULL;
     172        last = NULL;
     173        cancellation = NULL;
    110174}
    111175
    112176void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     177        state = Start;
    113178        self_cor{ info };
    114179        curr_cor = &self_cor;
     
    241306}
    242307
     308static int * __volatile_errno() __attribute__((noinline));
     309static int * __volatile_errno() { asm(""); return &errno; }
     310
    243311// KERNEL ONLY
    244312// runThread runs a thread by context switching
    245313// from the processor coroutine to the target thread
    246 static void runThread(processor * this, thread_desc * dst) {
    247         assert(dst->curr_cor);
     314static void runThread(processor * this, thread_desc * thrd_dst) {
    248315        coroutine_desc * proc_cor = get_coroutine(this->runner);
    249         coroutine_desc * thrd_cor = dst->curr_cor;
    250316
    251317        // Reset the terminating actions here
     
    253319
    254320        // Update global state
    255         kernelTLS.this_thread = dst;
    256 
    257         // Context Switch to the thread
    258         ThreadCtxSwitch(proc_cor, thrd_cor);
    259         // when ThreadCtxSwitch returns we are back in the processor coroutine
     321        kernelTLS.this_thread = thrd_dst;
     322
     323        // set state of processor coroutine to inactive and the thread to active
     324        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     325        thrd_dst->state = Active;
     326
     327        // set context switch to the thread that the processor is executing
     328        verify( thrd_dst->context.SP );
     329        CtxSwitch( &proc_cor->context, &thrd_dst->context );
     330        // when CtxSwitch returns we are back in the processor coroutine
     331
     332        // set state of processor coroutine to active and the thread to inactive
     333        thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
     334        proc_cor->state = Active;
    260335}
    261336
     
    263338static void returnToKernel() {
    264339        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    265         coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine;
    266         ThreadCtxSwitch(thrd_cor, proc_cor);
     340        thread_desc * thrd_src = kernelTLS.this_thread;
     341
     342        // set state of current coroutine to inactive
     343        thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
     344        proc_cor->state = Active;
     345        int local_errno = *__volatile_errno();
     346        #if defined( __i386 ) || defined( __x86_64 )
     347                __x87_store;
     348        #endif
     349
     350        // set new coroutine that the processor is executing
     351        // and context switch to it
     352        verify( proc_cor->context.SP );
     353        CtxSwitch( &thrd_src->context, &proc_cor->context );
     354
     355        // set state of new coroutine to active
     356        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     357        thrd_src->state = Active;
     358
     359        #if defined( __i386 ) || defined( __x86_64 )
     360                __x87_load;
     361        #endif
     362        *__volatile_errno() = local_errno;
    267363}
    268364
     
    307403        processor * proc = (processor *) arg;
    308404        kernelTLS.this_processor = proc;
    309         kernelTLS.this_coroutine = NULL;
    310405        kernelTLS.this_thread    = NULL;
    311406        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
     
    314409        // to waste the perfectly valid stack create by pthread.
    315410        current_stack_info_t info;
    316         machine_context_t ctx;
    317         info.context = &ctx;
     411        __stack_t ctx;
     412        info.storage = &ctx;
    318413        (proc->runner){ proc, &info };
    319414
    320         __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.base);
     415        __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
    321416
    322417        //Set global state
    323         kernelTLS.this_coroutine = get_coroutine(proc->runner);
    324418        kernelTLS.this_thread    = NULL;
    325419
     
    350444
    351445// KERNEL_ONLY
    352 void kernel_first_resume(processor * this) {
    353         coroutine_desc * src = kernelTLS.this_coroutine;
     446void kernel_first_resume( processor * this ) {
     447        thread_desc * src = mainThread;
    354448        coroutine_desc * dst = get_coroutine(this->runner);
    355449
    356450        verify( ! kernelTLS.preemption_state.enabled );
    357451
    358         create_stack(&dst->stack, dst->stack.size);
     452        __stack_prepare( &dst->stack, 65000 );
    359453        CtxStart(&this->runner, CtxInvokeCoroutine);
    360454
    361455        verify( ! kernelTLS.preemption_state.enabled );
    362456
    363         dst->last = src;
    364         dst->starter = dst->starter ? dst->starter : src;
     457        dst->last = &src->self_cor;
     458        dst->starter = dst->starter ? dst->starter : &src->self_cor;
    365459
    366460        // set state of current coroutine to inactive
    367461        src->state = src->state == Halted ? Halted : Inactive;
    368462
    369         // set new coroutine that task is executing
    370         kernelTLS.this_coroutine = dst;
    371 
    372         // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
    373         // Therefore, when first creating a coroutine, interrupts are enable before calling the main.
    374         // This is consistent with thread creation. However, when creating the main processor coroutine,
    375         // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will
    376         // stay disabled.
    377         disable_interrupts();
    378 
    379463        // context switch to specified coroutine
    380         assert( src->stack.context );
    381         CtxSwitch( src->stack.context, dst->stack.context );
     464        verify( dst->context.SP );
     465        CtxSwitch( &src->context, &dst->context );
    382466        // when CtxSwitch returns we are back in the src coroutine
    383467
     
    386470
    387471        verify( ! kernelTLS.preemption_state.enabled );
     472}
     473
     474// KERNEL_ONLY
     475void kernel_last_resume( processor * this ) {
     476        coroutine_desc * src = &mainThread->self_cor;
     477        coroutine_desc * dst = get_coroutine(this->runner);
     478
     479        verify( ! kernelTLS.preemption_state.enabled );
     480        verify( dst->starter == src );
     481        verify( dst->context.SP );
     482
     483        // context switch to the processor
     484        CtxSwitch( &src->context, &dst->context );
    388485}
    389486
     
    394491void ScheduleThread( thread_desc * thrd ) {
    395492        verify( thrd );
    396         verify( thrd->self_cor.state != Halted );
     493        verify( thrd->state != Halted );
    397494
    398495        verify( ! kernelTLS.preemption_state.enabled );
     
    551648        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    552649
     650        __page_size = sysconf( _SC_PAGESIZE );
     651
    553652        __cfa_dbg_global_clusters.list{ __get };
    554653        __cfa_dbg_global_clusters.lock{};
     
    565664        mainThread = (thread_desc *)&storage_mainThread;
    566665        current_stack_info_t info;
     666        info.storage = (__stack_t*)&storage_mainThreadCtx;
    567667        (*mainThread){ &info };
    568668
     
    599699        kernelTLS.this_processor = mainProcessor;
    600700        kernelTLS.this_thread    = mainThread;
    601         kernelTLS.this_coroutine = &mainThread->self_cor;
    602701
    603702        // Enable preemption
     
    634733        // which is currently here
    635734        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    636         returnToKernel();
     735        kernel_last_resume( kernelTLS.this_processor );
    637736        mainThread->self_cor.state = Halted;
    638737
     
    720819                __cfaabi_dbg_bits_write( abort_text, len );
    721820
    722                 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) {
    723                         len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine );
     821                if ( &thrd->self_cor != thrd->curr_cor ) {
     822                        len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor );
    724823                        __cfaabi_dbg_bits_write( abort_text, len );
    725824                }
  • libcfa/src/concurrency/thread.cfa

    r6a9d4b4 r933f32f  
    3131// Thread ctors and dtors
    3232void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
     33        context{ NULL, NULL };
    3334        self_cor{ name, storage, storageSize };
    34         verify(&self_cor);
     35        state = Start;
    3536        curr_cor = &self_cor;
    3637        self_mon.owner = &this;
     
    7374forall( dtype T | is_thread(T) )
    7475void __thrd_start( T& this ) {
    75         coroutine_desc* thrd_c = get_coroutine(this);
    76         thread_desc   * thrd_h = get_thread   (this);
    77         thrd_c->last = TL_GET( this_coroutine );
    78 
    79         // __cfaabi_dbg_print_safe("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
     76        thread_desc * this_thrd = get_thread(this);
     77        thread_desc * curr_thrd = TL_GET( this_thread );
    8078
    8179        disable_interrupts();
    82         create_stack(&thrd_c->stack, thrd_c->stack.size);
    83         kernelTLS.this_coroutine = thrd_c;
    8480        CtxStart(&this, CtxInvokeThread);
    85         assert( thrd_c->last->stack.context );
    86         CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
     81        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
     82        verify( this_thrd->context.SP );
     83        CtxSwitch( &curr_thrd->context, &this_thrd->context );
    8784
    88         ScheduleThread(thrd_h);
     85        ScheduleThread(this_thrd);
    8986        enable_interrupts( __cfaabi_dbg_ctx );
    9087}
     
    9289extern "C" {
    9390        // KERNEL ONLY
    94         void __finish_creation(void) {
    95                 coroutine_desc* thrd_c = kernelTLS.this_coroutine;
    96                 ThreadCtxSwitch( thrd_c, thrd_c->last );
     91        void __finish_creation(thread_desc * this) {
     92                // set new coroutine that the processor is executing
     93                // and context switch to it
     94                verify( kernelTLS.this_thread != this );
     95                verify( kernelTLS.this_thread->context.SP );
     96                CtxSwitch( &this->context, &kernelTLS.this_thread->context );
    9797        }
    9898}
     
    112112}
    113113
    114 // KERNEL ONLY
    115 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    116         // set state of current coroutine to inactive
    117         src->state = src->state == Halted ? Halted : Inactive;
    118         dst->state = Active;
    119 
    120         // set new coroutine that the processor is executing
    121         // and context switch to it
    122         kernelTLS.this_coroutine = dst;
    123         assert( src->stack.context );
    124         CtxSwitch( src->stack.context, dst->stack.context );
    125         kernelTLS.this_coroutine = src;
    126 
    127         // set state of new coroutine to active
    128         dst->state = dst->state == Halted ? Halted : Inactive;
    129         src->state = Active;
    130 }
    131 
    132114// Local Variables: //
    133115// mode: c //
  • libcfa/src/concurrency/thread.hfa

    r6a9d4b4 r933f32f  
    6161void ^?{}(thread_desc & this);
    6262
    63 static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 0 }; }
     63static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 65000 }; }
    6464static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
    6565static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
    66 static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 0 }; }
    67 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0, stackSize }; }
     66static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 65000 }; }
     67static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, NULL, stackSize }; }
    6868static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
    69 static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 0 }; }
    70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 0 }; }
     69static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 65000 }; }
     70static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 65000 }; }
    7171static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
    7272
  • libcfa/src/containers/maybe.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 24 15:40:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:23:50 2017
    13 // Update Count     : 2
     12// Last Modified On : Sun Feb 17 11:22:03 2019
     13// Update Count     : 3
    1414//
    1515
     
    3939forall(otype T)
    4040maybe(T) ?=?(maybe(T) & this, maybe(T) that) {
    41         if (this.has_value & that.has_value) {
     41        if (this.has_value && that.has_value) {
    4242                this.value = that.value;
    4343        } else if (this.has_value) {
  • libcfa/src/containers/result.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 24 15:40:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:23:58 2017
    13 // Update Count     : 2
     12// Last Modified On : Sun Feb 17 11:24:04 2019
     13// Update Count     : 3
    1414//
    1515
     
    4848forall(otype T, otype E)
    4949result(T, E) ?=?(result(T, E) & this, result(T, E) that) {
    50         if (this.has_value & that.has_value) {
     50        if (this.has_value && that.has_value) {
    5151                this.value = that.value;
    5252        } else if (this.has_value) {
  • libcfa/src/fstream.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 24 18:33:38 2018
    13 // Update Count     : 304
     12// Last Modified On : Thu May 16 08:33:28 2019
     13// Update Count     : 328
    1414//
    1515
     
    2323#include <complex.h>                                                                    // creal, cimag
    2424#include <assert.h>
     25#include <errno.h>                                                                              // errno
    2526
    2627#define IO_MSG "I/O error: "
    2728
    28 void ?{}( ofstream & os, void * file, bool sepDefault, bool sepOnOff, bool nlOnOff, bool prt, const char * separator, const char * tupleSeparator ) {
     29void ?{}( ofstream & os, void * file ) {
    2930        os.file = file;
    30         os.sepDefault = sepDefault;
    31         os.sepOnOff = sepOnOff;
    32         os.nlOnOff = nlOnOff;
    33         os.prt = prt;
    34         sepSet( os, separator );
     31        os.sepDefault = true;
     32        os.sepOnOff = false;
     33        os.nlOnOff = true;
     34        os.prt = false;
     35        os.sawNL = false;
     36        sepSet( os, " " );
    3537        sepSetCur( os, sepGet( os ) );
    36         sepSetTuple( os, tupleSeparator );
     38        sepSetTuple( os, ", " );
    3739}
    3840
     
    102104
    103105void open( ofstream & os, const char * name, const char * mode ) {
    104         FILE *file = fopen( name, mode );
     106        FILE * file = fopen( name, mode );
    105107        #ifdef __CFA_DEBUG__
    106108        if ( file == 0 ) {
    107                 fprintf( stderr, IO_MSG "open output file \"%s\", ", name );
    108                 perror( 0 );
    109                 exit( EXIT_FAILURE );
     109                abort( IO_MSG "open output file \"%s\", %s", name, strerror( errno ) );
    110110        } // if
    111111        #endif // __CFA_DEBUG__
    112         (os){ file, true, false, true, false, " ", ", " };
     112        (os){ file };
    113113} // open
    114114
     
    121121
    122122        if ( fclose( (FILE *)(os.file) ) == EOF ) {
    123                 perror( IO_MSG "close output" );
     123                abort( IO_MSG "close output %s", strerror( errno ) );
    124124        } // if
    125125} // close
     
    127127ofstream & write( ofstream & os, const char * data, size_t size ) {
    128128        if ( fail( os ) ) {
    129                 fprintf( stderr, "attempt write I/O on failed stream\n" );
    130                 exit( EXIT_FAILURE );
     129                abort( "attempt write I/O on failed stream\n" );
    131130        } // if
    132131
    133132        if ( fwrite( data, 1, size, (FILE *)(os.file) ) != size ) {
    134                 perror( IO_MSG "write" );
    135                 exit( EXIT_FAILURE );
     133                abort( IO_MSG "write %s", strerror( errno ) );
    136134        } // if
    137135        return os;
     
    144142        if ( len == EOF ) {
    145143                if ( ferror( (FILE *)(os.file) ) ) {
    146                         fprintf( stderr, "invalid write\n" );
    147                         exit( EXIT_FAILURE );
     144                        abort( "invalid write\n" );
    148145                } // if
    149146        } // if
     
    155152} // fmt
    156153
    157 static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_), true, false, true, false, " ", ", " };
     154static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_) };
    158155ofstream & sout = soutFile;
    159 static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_), true, false, true, false, " ", ", " };
     156static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_) };
    160157ofstream & serr = serrFile;
    161158
     159// static ofstream sexitFile = { (FILE *)(&_IO_2_1_stdout_) };
     160// ofstream & sexit = sexitFile;
     161// static ofstream sabortFile = { (FILE *)(&_IO_2_1_stderr_) };
     162// ofstream & sabort = sabortFile;
     163
     164void nl( ofstream & os ) {
     165        if ( getANL( os ) ) (ofstream &)(nl( os ));                     // implementation only
     166        else setPrt( os, false );                                                       // turn off
     167}
    162168
    163169//---------------------------------------
     
    166172void ?{}( ifstream & is, void * file ) {
    167173        is.file = file;
     174        is.nlOnOff = false;
    168175}
    169176
     
    177184        open( is, name, "r" );
    178185}
     186
     187void nlOn( ifstream & os ) { os.nlOnOff = true; }
     188void nlOff( ifstream & os ) { os.nlOnOff = false; }
     189bool getANL( ifstream & os ) { return os.nlOnOff; }
    179190
    180191int fail( ifstream & is ) {
     
    187198
    188199void open( ifstream & is, const char * name, const char * mode ) {
    189         FILE *file = fopen( name, mode );
     200        FILE * file = fopen( name, mode );
    190201        #ifdef __CFA_DEBUG__
    191202        if ( file == 0 ) {
    192                 fprintf( stderr, IO_MSG "open input file \"%s\", ", name );
    193                 perror( 0 );
    194                 exit( EXIT_FAILURE );
     203                abort( IO_MSG "open input file \"%s\", %s\n", name, strerror( errno ) );
    195204        } // if
    196205        #endif // __CFA_DEBUG__
     
    206215
    207216        if ( fclose( (FILE *)(is.file) ) == EOF ) {
    208                 perror( IO_MSG "close input" );
     217                abort( IO_MSG "close input %s", strerror( errno ) );
    209218        } // if
    210219} // close
     
    212221ifstream & read( ifstream & is, char * data, size_t size ) {
    213222        if ( fail( is ) ) {
    214                 fprintf( stderr, "attempt read I/O on failed stream\n" );
    215                 exit( EXIT_FAILURE );
     223                abort( "attempt read I/O on failed stream\n" );
    216224        } // if
    217225
    218226        if ( fread( data, size, 1, (FILE *)(is.file) ) == 0 ) {
    219                 perror( IO_MSG "read" );
    220                 exit( EXIT_FAILURE );
     227                abort( IO_MSG "read %s", strerror( errno ) );
    221228        } // if
    222229        return is;
     
    225232ifstream &ungetc( ifstream & is, char c ) {
    226233        if ( fail( is ) ) {
    227                 fprintf( stderr, "attempt ungetc I/O on failed stream\n" );
    228                 exit( EXIT_FAILURE );
     234                abort( "attempt ungetc I/O on failed stream\n" );
    229235        } // if
    230236
    231237        if ( ungetc( c, (FILE *)(is.file) ) == EOF ) {
    232                 perror( IO_MSG "ungetc" );
    233                 exit( EXIT_FAILURE );
     238                abort( IO_MSG "ungetc %s", strerror( errno ) );
    234239        } // if
    235240        return is;
     
    243248        if ( len == EOF ) {
    244249                if ( ferror( (FILE *)(is.file) ) ) {
    245                         fprintf( stderr, "invalid read\n" );
    246                         exit( EXIT_FAILURE );
     250                        abort( "invalid read\n" );
    247251                } // if
    248252        } // if
  • libcfa/src/fstream.hfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 24 18:33:41 2018
    13 // Update Count     : 149
     12// Last Modified On : Thu May 16 08:34:10 2019
     13// Update Count     : 157
    1414//
    1515
     
    7070extern ofstream & sout, & serr;
    7171
     72// extern ofstream & sout, & serr, & sexit, & sabort;
     73// void nl( ofstream & os );
     74
    7275
    7376struct ifstream {
    7477        void * file;
     78        bool nlOnOff;
    7579}; // ifstream
    7680
    7781// public
     82void nlOn( ifstream & );
     83void nlOff( ifstream & );
     84bool getANL( ifstream & );
    7885int fail( ifstream & is );
    7986int eof( ifstream & is );
  • libcfa/src/gmp.hfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Tue Apr 19 08:43:43 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Dec  4 23:25:51 2018
    13 // Update Count     : 22
     12// Last Modified On : Sat Apr 20 09:01:52 2019
     13// Update Count     : 24
    1414//
    1515
     
    271271
    272272        void ?|?( ostype & os, Int mp ) {
    273                 (ostype)(os | mp); if ( getANL( os ) ) nl( os );
     273                (ostype)(os | mp); nl( os );
    274274        } // ?|?
    275275} // distribution
  • libcfa/src/heap.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Sep  6 09:01:30 2018
    13 // Update Count     : 513
     12// Last Modified On : Thu May  9 16:29:12 2019
     13// Update Count     : 516
    1414//
    1515
     
    220220                StackLF<Storage> freeList;
    221221                #else
    222                 #error undefined lock type for bucket lock
     222                        #error undefined lock type for bucket lock
    223223                #endif // SPINLOCK
    224224                size_t blockSize;                                                               // size of allocations on this list
     
    234234}; // HeapManager
    235235
     236
    236237static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     238
    237239// statically allocated variables => zero filled.
    238 
    239 
    240240static size_t pageSize;                                                                 // architecture pagesize
    241241static size_t heapExpand;                                                               // sbrk advance
     
    306306        sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    307307        heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
    308                            } // HeapManager
     308} // HeapManager
    309309
    310310
     
    316316        // } // if
    317317        #endif // __STATISTICS__
    318                                 } // ~HeapManager
     318} // ~HeapManager
    319319
    320320
     
    533533
    534534static inline void * doMalloc( size_t size ) with ( heapManager ) {
    535         HeapManager.Storage * block;
     535        HeapManager.Storage * block;                                            // pointer to new block of storage
    536536
    537537        // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
     
    656656        __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );
    657657        if ( traceHeap() ) {
    658                 char helpText[64];
     658                enum { BufferSize = 64 };
     659                char helpText[BufferSize];
    659660                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    660661                __cfaabi_dbg_bits_write( helpText, len );
     
    853854                        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    854855                        if ( ! mapped )
    855                                 #endif // __CFA_DEBUG__
     856                        #endif // __CFA_DEBUG__
    856857                                memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part
    857858                        header->kind.real.blockSize |= 2;                       // mark new request as zero fill
     
    10341035// Local Variables: //
    10351036// tab-width: 4 //
    1036 // compile-command: "cfa -nodebug -O2 heap.c" //
     1037// compile-command: "cfa -nodebug -O2 heap.cfa" //
    10371038// End: //
  • libcfa/src/iostream.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 24 18:33:40 2018
    13 // Update Count     : 589
     12// Last Modified On : Sun May 19 10:48:27 2019
     13// Update Count     : 654
    1414//
    1515
     
    2323extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
    2424#include <float.h>                                                                              // DBL_DIG, LDBL_DIG
     25#include <math.h>                                                                               // isfinite
    2526#include <complex.h>                                                                    // creal, cimag
    2627}
    2728
    2829forall( dtype ostype | ostream( ostype ) ) {
     30        ostype & ?|?( ostype & os, zero_t ) {
     31                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     32                fmt( os, "%d", 0n );
     33                return os;
     34        } // ?|?
     35        void ?|?( ostype & os, zero_t z ) {
     36                (ostype &)(os | z); nl( os );
     37        } // ?|?
     38
     39        ostype & ?|?( ostype & os, one_t ) {
     40                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     41                fmt( os, "%d", 1n );
     42                return os;
     43        } // ?|?
     44        void ?|?( ostype & os, one_t o ) {
     45                (ostype &)(os | o); nl( os );
     46        } // ?|?
     47
    2948        ostype & ?|?( ostype & os, bool b ) {
    3049                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     
    135154        } // ?|?
    136155
     156        static void checkDecPt( ostype & os, const char * buf, int len ) {
     157                for ( int i = 0;; i += 1 ) {
     158                        if ( i == len ) { fmt( os, "." ); break; }
     159                        if ( buf[i] == '.' ) break;
     160                } // for
     161        } // checkDecPt
     162
    137163        ostype & ?|?( ostype & os, float f ) {
    138164                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    139                 fmt( os, "%g", f );
     165                char buf[48];
     166                int len = snprintf( buf, 48, "%g", f );
     167                fmt( os, "%s", buf );
     168                if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
    140169                return os;
    141170        } // ?|?
     
    146175        ostype & ?|?( ostype & os, double d ) {
    147176                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    148                 fmt( os, "%.*lg", DBL_DIG, d );
     177                char buf[48];
     178                int len = snprintf( buf, 48, "%.*lg", DBL_DIG, d );
     179                fmt( os, "%s", buf );
     180                if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
    149181                return os;
    150182        } // ?|?
     
    155187        ostype & ?|?( ostype & os, long double ld ) {
    156188                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    157                 fmt( os, "%.*Lg", LDBL_DIG, ld );
     189                char buf[48];
     190                int len = snprintf( buf, 48, "%.*Lg", LDBL_DIG, ld );
     191                fmt( os, "%s", buf );
     192                if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
    158193                return os;
    159194        } // ?|?
     
    164199        ostype & ?|?( ostype & os, float _Complex fc ) {
    165200                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    166                 fmt( os, "%g%+gi", crealf( fc ), cimagf( fc ) );
     201//              os | crealf( fc ) | nonl;
     202                float f = crealf( fc );
     203                char buf[48];
     204                int len = snprintf( buf, 48, "%g", f );
     205                fmt( os, "%s", buf );
     206                if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
     207                f = cimagf( fc );
     208                len = snprintf( buf, 48, "%+g", f );
     209                fmt( os, "%s", buf );
     210                if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
     211                fmt( os, "i" );
    167212                return os;
    168213        } // ?|?
     
    173218        ostype & ?|?( ostype & os, double _Complex dc ) {
    174219                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    175                 fmt( os, "%.*lg%+.*lgi", DBL_DIG, creal( dc ), DBL_DIG, cimag( dc ) );
     220//              os | creal( dc ) | nonl;
     221                double d = creal( dc );
     222                char buf[48];
     223                int len = snprintf( buf, 48, "%.*lg", DBL_DIG, d );
     224                fmt( os, "%s", buf );
     225                if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
     226                d = cimag( dc );
     227                len = snprintf( buf, 48, "%+.*lg", DBL_DIG, d );
     228                fmt( os, "%s", buf );
     229                if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
     230                fmt( os, "i" );
    176231                return os;
    177232        } // ?|?
     
    182237        ostype & ?|?( ostype & os, long double _Complex ldc ) {
    183238                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    184                 fmt( os, "%.*Lg%+.*Lgi", LDBL_DIG, creall( ldc ), LDBL_DIG, cimagl( ldc ) );
     239//              os | creall( ldc ) || nonl;
     240                long double ld = creall( ldc );
     241                char buf[48];
     242                int len = snprintf( buf, 48, "%.*Lg", LDBL_DIG, ld );
     243                fmt( os, "%s", buf );
     244                if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
     245                ld = cimagl( ldc );
     246                len = snprintf( buf, 48, "%+.*Lg", LDBL_DIG, ld );
     247                fmt( os, "%s", buf );
     248                if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
     249                fmt( os, "i" );
    185250                return os;
    186251        } // ?|?
     
    378443
    379444        istype & ?|?( istype & is, char & c ) {
    380                 fmt( is, "%c", &c );                                                    // must pass pointer through varg to fmt
     445                char temp;
     446                for () {
     447                        fmt( is, "%c", &temp );                                                 // must pass pointer through varg to fmt
     448                        // do not overwrite parameter with newline unless appropriate
     449                        if ( temp != '\n' || getANL( is ) ) { c = temp; break; }
     450                        if ( eof( is ) ) break;
     451                } // for
    381452                return is;
    382453        } // ?|?
     
    470541        } // ?|?
    471542
    472 
    473543        // manipulators
    474544        istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
     
    477547
    478548        istype & nl( istype & is ) {
    479                 fmt( is, "%*[ \t\f\n\r\v]" );                                   // ignore whitespace
     549                fmt( is, "%*[^\n]" );                                                   // ignore characters to newline
    480550                return is;
    481551        } // nl
     552
     553        istype & nlOn( istype & is ) {
     554                nlOn( is );                                                                             // call void returning
     555                return is;
     556        } // nlOn
     557
     558        istype & nlOff( istype & is ) {
     559                nlOff( is );                                                                    // call void returning
     560                return is;
     561        } // nlOff
    482562} // distribution
    483563
  • libcfa/src/iostream.hfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 24 18:33:40 2018
    13 // Update Count     : 220
     12// Last Modified On : Sat May 11 10:31:27 2019
     13// Update Count     : 232
    1414//
    1515
     
    4848        void close( ostype & os );
    4949        ostype & write( ostype &, const char *, size_t );
    50         int fmt( ostype &, const char format[], ... );
     50        int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    5151}; // ostream
    5252
     
    6262
    6363forall( dtype ostype | ostream( ostype ) ) {
     64        ostype & ?|?( ostype &, zero_t );
     65        void ?|?( ostype &, zero_t );
     66        ostype & ?|?( ostype &, one_t );
     67        void ?|?( ostype &, one_t );
     68
    6469        ostype & ?|?( ostype &, bool );
    6570        void ?|?( ostype &, bool );
     
    144149
    145150trait istream( dtype istype ) {
     151        void nlOn( istype & );                                                          // read newline
     152        void nlOff( istype & );                                                         // scan newline
     153        bool getANL( istype & );                                                        // get scan newline (on/off)
    146154        int fail( istype & );
    147155        int eof( istype & );
     
    150158        istype & read( istype &, char *, size_t );
    151159        istype & ungetc( istype &, char );
    152         int fmt( istype &, const char format[], ... );
     160        int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
    153161}; // istream
    154162
     
    184192        istype & ?|?( istype &, istype & (*)( istype & ) );
    185193        istype & nl( istype & is );
     194        istype & nlOn( istype & );
     195        istype & nlOff( istype & );
    186196} // distribution
    187197
     
    205215
    206216// Local Variables: //
    207 // mode: c //
    208217// tab-width: 4 //
    209218// End: //
  • libcfa/src/rational.cfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 23 22:56:49 2018
    13 // Update Count     : 170
     12// Last Modified On : Thu Mar 28 17:33:03 2019
     13// Update Count     : 181
    1414//
    1515
     
    3535        static RationalImpl simplify( RationalImpl & n, RationalImpl & d ) {
    3636                if ( d == (RationalImpl){0} ) {
    37                         serr | "Invalid rational number construction: denominator cannot be equal to 0.";
    38                         exit( EXIT_FAILURE );
     37                        abort( "Invalid rational number construction: denominator cannot be equal to 0.\n" );
    3938                } // exit
    4039                if ( d < (RationalImpl){0} ) { d = -d; n = -n; } // move sign to numerator
     
    5453        void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) {
    5554                RationalImpl t = simplify( n, d );                              // simplify
    56                 r.numerator = n / t;
    57                 r.denominator = d / t;
     55                r.[numerator, denominator] = [n / t, d / t];
    5856        } // rational
    5957
     
    7876                RationalImpl prev = r.numerator;
    7977                RationalImpl t = gcd( abs( n ), r.denominator ); // simplify
    80                 r.numerator = n / t;
    81                 r.denominator = r.denominator / t;
     78                r.[numerator, denominator] = [n / t, r.denominator / t];
    8279                return prev;
    8380        } // numerator
     
    8683                RationalImpl prev = r.denominator;
    8784                RationalImpl t = simplify( r.numerator, d );    // simplify
    88                 r.numerator = r.numerator / t;
    89                 r.denominator = d / t;
     85                r.[numerator, denominator] = [r.numerator / t, d / t];
    9086                return prev;
    9187        } // denominator
     
    120116
    121117        Rational(RationalImpl) +?( Rational(RationalImpl) r ) {
    122                 Rational(RationalImpl) t = { r.numerator, r.denominator };
    123                 return t;
     118                return (Rational(RationalImpl)){ r.numerator, r.denominator };
    124119        } // +?
    125120
    126121        Rational(RationalImpl) -?( Rational(RationalImpl) r ) {
    127                 Rational(RationalImpl) t = { -r.numerator, r.denominator };
    128                 return t;
     122                return (Rational(RationalImpl)){ -r.numerator, r.denominator };
    129123        } // -?
    130124
    131125        Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    132126                if ( l.denominator == r.denominator ) {                 // special case
    133                         Rational(RationalImpl) t = { l.numerator + r.numerator, l.denominator };
    134                         return t;
     127                        return (Rational(RationalImpl)){ l.numerator + r.numerator, l.denominator };
    135128                } else {
    136                         Rational(RationalImpl) t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    137                         return t;
     129                        return (Rational(RationalImpl)){ l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    138130                } // if
    139131        } // ?+?
     
    141133        Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    142134                if ( l.denominator == r.denominator ) {                 // special case
    143                         Rational(RationalImpl) t = { l.numerator - r.numerator, l.denominator };
    144                         return t;
     135                        return (Rational(RationalImpl)){ l.numerator - r.numerator, l.denominator };
    145136                } else {
    146                         Rational(RationalImpl) t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    147                         return t;
     137                        return (Rational(RationalImpl)){ l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    148138                } // if
    149139        } // ?-?
    150140
    151141        Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    152                 Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator };
    153                 return t;
     142                return (Rational(RationalImpl)){ l.numerator * r.numerator, l.denominator * r.denominator };
    154143        } // ?*?
    155144
    156145        Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    157146                if ( r.numerator < (RationalImpl){0} ) {
    158                         r.numerator = -r.numerator;
    159                         r.denominator = -r.denominator;
     147                        r.[numerator, denominator] = [-r.numerator, -r.denominator];
    160148                } // if
    161                 Rational(RationalImpl) t = { l.numerator * r.denominator, l.denominator * r.numerator };
    162                 return t;
     149                return (Rational(RationalImpl)){ l.numerator * r.denominator, l.denominator * r.numerator };
    163150        } // ?/?
    164151
     
    167154        forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    168155        istype & ?|?( istype & is, Rational(RationalImpl) & r ) {
    169                 RationalImpl t;
    170156                is | r.numerator | r.denominator;
    171                 t = simplify( r.numerator, r.denominator );
     157                RationalImpl t = simplify( r.numerator, r.denominator );
    172158                r.numerator /= t;
    173159                r.denominator /= t;
     
    185171        } // distribution
    186172} // distribution
     173
     174forall( otype RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } )
     175Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y ) {
     176        if ( y < 0 ) {
     177                return (Rational(RationalImpl)){ x.denominator \ -y, x.numerator \ -y };
     178        } else {
     179                return (Rational(RationalImpl)){ x.numerator \ y, x.denominator \ y };
     180        } // if
     181}
    187182
    188183// conversion
  • libcfa/src/rational.hfa

    r6a9d4b4 r933f32f  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Tue Dec  4 23:07:46 2018
    15 // Update Count     : 106
     14// Last Modified On : Tue Mar 26 23:16:10 2019
     15// Update Count     : 109
    1616//
    1717
     
    9898} // distribution
    9999
     100forall( otype RationalImpl | arithmetic( RationalImpl ) |{RationalImpl ?\?( RationalImpl, unsigned long );} )
     101Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y );
     102
    100103// conversion
    101104forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
  • libcfa/src/stdhdr/stdbool.h

    r6a9d4b4 r933f32f  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul  5 20:39:51 2016
    13 // Update Count     : 12
     12// Last Modified On : Mon Mar 25 08:00:08 2019
     13// Update Count     : 15
    1414//
    1515
    1616extern "C" {
    1717#include_next <stdbool.h>                                                               // has internal check for multiple expansion
     18
     19// allows printing as true/false
     20#if defined( true )
     21#undef true
     22#define true ((_Bool)1)
     23#endif // true
     24
     25#if defined( false )
     26#undef false
     27#define false ((_Bool)0)
     28#endif // false
    1829} // extern "C"
    1930
  • libcfa/src/stdlib.hfa

    r6a9d4b4 r933f32f  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 17 15:37:45 2018
    13 // Update Count     : 346
     12// Last Modified On : Wed Apr 24 17:35:43 2019
     13// Update Count     : 352
    1414//
    1515
     
    4040        } // malloc
    4141
    42         // T & malloc( void ) {
    43         //      int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    44         //      printf( "& malloc %p\n", &p );
    45         //      return p;
    46         //      //      return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    47         // } // malloc
    48 
    4942        T * calloc( size_t dim ) {
    5043                return (T *)(void *)calloc( dim, sizeof(T) );   // C calloc
     
    7669        T * alloc( char fill ) {
    7770                T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) );     // C malloc
    78                 return (T *)memset( ptr, (int)fill, sizeof(T) );        // initial with fill value
     71                return (T *)memset( ptr, (int)fill, sizeof(T) ); // initialize with fill value
    7972        } // alloc
    8073
     
    8477
    8578        T * alloc( size_t dim, char fill ) {
    86                 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
    87                 return (T *)memset( ptr, (int)fill, dim * sizeof(T) );    // initial with fill value
     79                T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C calloc
     80                return (T *)memset( ptr, (int)fill, dim * sizeof(T) ); // initialize with fill value
    8881        } // alloc
    8982
  • libcfa/src/time.hfa

    r6a9d4b4 r933f32f  
    3030
    3131static inline {
    32         Duration ?=?( Duration & dur, zero_t ) { return dur{ 0 }; }
     32        Duration ?=?( Duration & dur, __attribute__((unused)) zero_t ) { return dur{ 0 }; }
    3333
    3434        Duration +?( Duration rhs ) with( rhs ) {       return (Duration)@{ +tv }; }
     
    5959        bool ?>=?( Duration lhs, Duration rhs ) { return lhs.tv >= rhs.tv; }
    6060
    61         bool ?==?( Duration lhs, zero_t ) { return lhs.tv == 0; }
    62         bool ?!=?( Duration lhs, zero_t ) { return lhs.tv != 0; }
    63         bool ?<? ( Duration lhs, zero_t ) { return lhs.tv <  0; }
    64         bool ?<=?( Duration lhs, zero_t ) { return lhs.tv <= 0; }
    65         bool ?>? ( Duration lhs, zero_t ) { return lhs.tv >  0; }
    66         bool ?>=?( Duration lhs, zero_t ) { return lhs.tv >= 0; }
     61        bool ?==?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv == 0; }
     62        bool ?!=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv != 0; }
     63        bool ?<? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv <  0; }
     64        bool ?<=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv <= 0; }
     65        bool ?>? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv >  0; }
     66        bool ?>=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv >= 0; }
    6767
    6868        Duration abs( Duration rhs ) { return rhs.tv >= 0 ? rhs : -rhs; }
     
    101101        void ?{}( timeval & t, time_t sec, suseconds_t usec ) { t.tv_sec = sec; t.tv_usec = usec; }
    102102        void ?{}( timeval & t, time_t sec ) { t{ sec, 0 }; }
    103         void ?{}( timeval & t, zero_t ) { t{ 0, 0 }; }
    104 
    105         timeval ?=?( timeval & t, zero_t ) { return t{ 0 }; }
     103        void ?{}( timeval & t, __attribute__((unused)) zero_t ) { t{ 0, 0 }; }
     104
     105        timeval ?=?( timeval & t, __attribute__((unused)) zero_t ) { return t{ 0 }; }
    106106        timeval ?+?( timeval lhs, timeval rhs ) { return (timeval)@{ lhs.tv_sec + rhs.tv_sec, lhs.tv_usec + rhs.tv_usec }; }
    107107        timeval ?-?( timeval lhs, timeval rhs ) { return (timeval)@{ lhs.tv_sec - rhs.tv_sec, lhs.tv_usec - rhs.tv_usec }; }
     
    116116        void ?{}( timespec & t, time_t sec, __syscall_slong_t nsec ) { t.tv_sec = sec; t.tv_nsec = nsec; }
    117117        void ?{}( timespec & t, time_t sec ) { t{ sec, 0}; }
    118         void ?{}( timespec & t, zero_t ) { t{ 0, 0 }; }
    119 
    120         timespec ?=?( timespec & t, zero_t ) { return t{ 0 }; }
     118        void ?{}( timespec & t, __attribute__((unused)) zero_t ) { t{ 0, 0 }; }
     119
     120        timespec ?=?( timespec & t, __attribute__((unused)) zero_t ) { return t{ 0 }; }
    121121        timespec ?+?( timespec lhs, timespec rhs ) { return (timespec)@{ lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec }; }
    122122        timespec ?-?( timespec lhs, timespec rhs ) { return (timespec)@{ lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec }; }
     
    145145void ?{}( Time & time, int year, int month = 0, int day = 0, int hour = 0, int min = 0, int sec = 0, int nsec = 0 );
    146146static inline {
    147         Time ?=?( Time & time, zero_t ) { return time{ 0 }; }
     147        Time ?=?( Time & time, __attribute__((unused)) zero_t ) { return time{ 0 }; }
    148148
    149149        void ?{}( Time & time, timeval t ) with( time ) { tv = (int64_t)t.tv_sec * TIMEGRAN + t.tv_usec * 1000; }
  • libcfa/src/time_t.hfa

    r6a9d4b4 r933f32f  
    2424
    2525static inline void ?{}( Duration & dur ) with( dur ) { tv = 0; }
    26 static inline void ?{}( Duration & dur, zero_t ) with( dur ) { tv = 0; }
     26static inline void ?{}( Duration & dur, __attribute__((unused)) zero_t ) with( dur ) { tv = 0; }
    2727
    2828
     
    3434
    3535static inline void ?{}( Time & time ) with( time ) { tv = 0; }
    36 static inline void ?{}( Time & time, zero_t ) with( time ) { tv = 0; }
     36static inline void ?{}( Time & time, __attribute__((unused)) zero_t ) with( time ) { tv = 0; }
    3737
    3838// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.