- Timestamp:
- May 24, 2019, 10:19:41 AM (6 years ago)
- 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. - Location:
- libcfa
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/configure
r6a9d4b4 r933f32f 2382 2382 2383 2383 2384 # http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_check_compile_flag.m4 2385 2384 2386 2385 2387 am__api_version='1.15' … … 2957 2959 case $CONFIGURATION in 2958 2960 "debug" ) 2959 CONFIG_CFLAGS="-O 0-g"2961 CONFIG_CFLAGS="-Og -g" 2960 2962 CONFIG_CFAFLAGS="-debug" 2961 2963 CONFIG_BUILDLIB="yes" 2962 2964 ;; 2963 2965 "nodebug" ) 2964 CONFIG_CFLAGS="-O 2-s"2966 CONFIG_CFLAGS="-O3 -s" 2965 2967 CONFIG_CFAFLAGS="-nodebug" 2966 2968 CONFIG_BUILDLIB="yes" 2967 2969 ;; 2968 2970 "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" 2970 2977 CONFIG_CFAFLAGS="-nodebug" 2971 CONFIG_BUILDLIB=" no"2978 CONFIG_BUILDLIB="yes" 2972 2979 ;; 2973 2980 *) … … 2975 2982 ;; 2976 2983 esac 2984 2985 CONFIG_CFAFLAGS="${CONFIG_CFAFLAGS} ${CFAFLAGS}" 2977 2986 2978 2987 -
libcfa/configure.ac
r6a9d4b4 r933f32f 45 45 case $CONFIGURATION in 46 46 "debug" ) 47 CONFIG_CFLAGS="-O 0-g"47 CONFIG_CFLAGS="-Og -g" 48 48 CONFIG_CFAFLAGS="-debug" 49 49 CONFIG_BUILDLIB="yes" 50 50 ;; 51 51 "nodebug" ) 52 CONFIG_CFLAGS="-O 2-s"52 CONFIG_CFLAGS="-O3 -s" 53 53 CONFIG_CFAFLAGS="-nodebug" 54 54 CONFIG_BUILDLIB="yes" 55 55 ;; 56 56 "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" 58 63 CONFIG_CFAFLAGS="-nodebug" 59 CONFIG_BUILDLIB=" no"64 CONFIG_BUILDLIB="yes" 60 65 ;; 61 66 *) … … 63 68 ;; 64 69 esac 70 71 CONFIG_CFAFLAGS="${CONFIG_CFAFLAGS} ${CFAFLAGS}" 65 72 66 73 AC_SUBST(CONFIG_CFLAGS) -
libcfa/prelude/builtins.c
r6a9d4b4 r933f32f 10 10 // Created On : Fri Jul 21 16:21:03 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 5 21:40:38 201813 // Update Count : 2012 // Last Modified On : Tue Mar 26 23:10:36 2019 13 // Update Count : 95 14 14 // 15 15 … … 42 42 typedef unsigned long long __cfaabi_abi_exception_type_t; 43 43 44 #include <limits.h> // CHAR_BIT 44 45 #include "../src/virtual.h" 45 46 #include "../src/exception.h" … … 50 51 // increment/decrement unification 51 52 52 static inline forall( dtype T | { T& ?+=?( T&, one_t ); } ) 53 T& ++? ( T& x ) { return x += 1; } 53 static inline { 54 forall( dtype DT | { DT & ?+=?( DT &, one_t ); } ) 55 DT & ++?( DT & x ) { return x += 1; } 54 56 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; } 57 59 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; } 60 62 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. 69 static inline forall( dtype DT | sized(DT) ) DT * intptr( uintptr_t addr ) { return (DT *)addr; } 63 70 64 71 // exponentiation operator implementation … … 73 80 } // extern "C" 74 81 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 ); } 82 static 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 81 90 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 92 94 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 103 106 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 } // ?\? 107 static 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 115 114 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__() 120 121 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. 122 static 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 125 126 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__ 131 130 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; } 131 static 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 136 137 137 138 // 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 2 2 #include <stdint.h> // intX_t, uintX_t, where X is 8, 16, 32, 64 3 3 #include <uchar.h> // char16_t, char32_t -
libcfa/prelude/extras.regx
r6a9d4b4 r933f32f 1 1 typedef.* size_t; 2 2 typedef.* ptrdiff_t; 3 typedef.* intptr_t; 4 typedef.* uintptr_t; 3 5 typedef.* __int8_t; 4 6 typedef.* __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 1 16 #include <algorithm> 2 17 #include <array> … … 11 26 bool hasComparison; 12 27 } 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 , }, 16 31 { "signed short" , false, true , }, 17 32 { "unsigned short" , false, true , }, … … 34 49 #if defined(__i386__) || defined(__ia64__) || defined(__x86_64__) 35 50 { "__float80" , true , true , }, 36 { "_ Float128", true , true , },51 { "__float128" , true , true , }, 37 52 #endif 38 53 }; … … 103 118 { "?!=?", false, "signed int", Normal, "" }, 104 119 { "?=?", true, "", Normal, "" }, // void * LHS, zero_t RHS ??? 105 { "*?", false, "&", Normal, " | sized(DT)" }, // & ??? 120 // { "*?", false, "&", Normal, " | sized(DT)" }, // & ??? 121 { "*?", false, "&", Normal, "" }, // & ??? 106 122 107 123 { "?-?", false, "ptrdiff_t", Normal, " | sized(DT)" }, … … 150 166 cout << endl; 151 167 152 cout << "signed int ?==?( zero_t, zero_t ), 153 cout << "signed int ?==?( one_t, one_t ), 154 cout << "signed int ?==?( _Bool, _Bool ), 155 cout << "signed int 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; 156 172 157 173 for (auto op : arithmeticOperators) { … … 188 204 cout << "// Arithmetic Constructors //" << endl; 189 205 cout << "/////////////////////////////" << endl; 206 cout << endl; 207 190 208 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 << ")"; 196 214 } 197 215 cout << ";" << endl; 198 cout << "void \t^?{}( " << type << " & );" << endl;216 cout << "void ^?{}( " << type << " & );" << endl; 199 217 }; 200 218 201 219 otype("zero_t"); 220 cout << endl; 202 221 otype("one_t"); 222 cout << endl; 203 223 otype("_Bool", true); 204 otype("char", true); 205 otype("signed char", true); 206 otype("unsigned char", true); 224 cout << endl; 207 225 208 226 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; 211 231 cout << "void ^?{}(" << type.name << " &);" << endl; 212 232 cout << endl; … … 217 237 cout << "// Pointer Constructors //" << endl; 218 238 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; 221 243 222 244 // generate qualifiers … … 242 264 for (auto cvq : qualifiersPair) { 243 265 for (auto is_vol : { " ", "volatile" }) { 244 cout << "forall(dtype DT) void 266 cout << "forall(dtype DT) void ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl; 245 267 } 246 268 } 247 269 for (auto cvq : qualifiersSingle) { 248 270 for (auto is_vol : { " ", "volatile" }) { 249 cout << "forall(dtype DT) void 271 cout << "forall(dtype DT) void ?{}(" << cvq << type << " * " << is_vol << " &);" << endl; 250 272 } 251 273 for (auto is_vol : { " ", "volatile" }) { … … 269 291 cout << "forall(ftype FT) FT * ?=?( FT * &, zero_t );" << endl; 270 292 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; 273 295 cout << endl; 274 296 … … 277 299 cout << "///////////////////////" << endl; 278 300 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; 286 307 287 308 for (auto op : pointerOperators) { … … 387 408 } 388 409 410 // Local Variables: // 411 // tab-width: 4 // 412 // End: // -
libcfa/prelude/sync-builtins.cf
r6a9d4b4 r933f32f 323 323 _Bool __sync_bool_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...); 324 324 #endif 325 forall(dtype T) _Bool __sync_bool_compare_and_swap(T * volatile *, T *, T*, ...); 325 326 326 327 char __sync_val_compare_and_swap(volatile char *, char, char,...); … … 348 349 unsigned __int128 __sync_val_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...); 349 350 #endif 351 forall(dtype T) T * __sync_val_compare_and_swap(T * volatile *, T *, T*,...); 350 352 351 353 char __sync_lock_test_and_set(volatile char *, char,...); … … 434 436 #endif 435 437 436 char __atomic_exchange_n(volatile char *, volatile char *, int);438 char __atomic_exchange_n(volatile char *, char, int); 437 439 char __atomic_exchange_1(volatile char *, char, int); 438 440 void __atomic_exchange(volatile char *, volatile char *, volatile char *, int); 439 signed char __atomic_exchange_n(volatile signed char *, volatile signed char *, int);441 signed char __atomic_exchange_n(volatile signed char *, signed char, int); 440 442 signed char __atomic_exchange_1(volatile signed char *, signed char, int); 441 443 void __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);444 unsigned char __atomic_exchange_n(volatile unsigned char *, unsigned char, int); 443 445 unsigned char __atomic_exchange_1(volatile unsigned char *, unsigned char, int); 444 446 void __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);447 signed short __atomic_exchange_n(volatile signed short *, signed short, int); 446 448 signed short __atomic_exchange_2(volatile signed short *, signed short, int); 447 449 void __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);450 unsigned short __atomic_exchange_n(volatile unsigned short *, unsigned short, int); 449 451 unsigned short __atomic_exchange_2(volatile unsigned short *, unsigned short, int); 450 452 void __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);453 signed int __atomic_exchange_n(volatile signed int *, signed int, int); 452 454 signed int __atomic_exchange_4(volatile signed int *, signed int, int); 453 455 void __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);456 unsigned int __atomic_exchange_n(volatile unsigned int *, unsigned int, int); 455 457 unsigned int __atomic_exchange_4(volatile unsigned int *, unsigned int, int); 456 458 void __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);459 signed long long int __atomic_exchange_n(volatile signed long long int *, signed long long int, int); 458 460 signed long long int __atomic_exchange_8(volatile signed long long int *, signed long long int, int); 459 461 void __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);462 unsigned long long int __atomic_exchange_n(volatile unsigned long long int *, unsigned long long int, int); 461 463 unsigned long long int __atomic_exchange_8(volatile unsigned long long int *, unsigned long long int, int); 462 464 void __atomic_exchange(volatile unsigned long long int *, volatile unsigned long long int *, volatile unsigned long long int *, int); 463 465 #if defined(__SIZEOF_INT128__) 464 signed __int128 __atomic_exchange_n(volatile signed __int128 *, volatile signed __int128 *, int);466 signed __int128 __atomic_exchange_n(volatile signed __int128 *, signed __int128, int); 465 467 signed __int128 __atomic_exchange_16(volatile signed __int128 *, signed __int128, int); 466 468 void __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);469 unsigned __int128 __atomic_exchange_n(volatile unsigned __int128 *, unsigned __int128, int); 468 470 unsigned __int128 __atomic_exchange_16(volatile unsigned __int128 *, unsigned __int128, int); 469 471 void __atomic_exchange(volatile unsigned __int128 *, volatile unsigned __int128 *, volatile unsigned __int128 *, int); 470 472 #endif 473 forall(dtype T) T * __atomic_exchange_n(T * volatile *, T *, int); 474 forall(dtype T) void __atomic_exchange(T * volatile *, T * volatile *, T * volatile *, int); 471 475 472 476 _Bool __atomic_load_n(const volatile _Bool *, int); … … 507 511 void __atomic_load(const volatile unsigned __int128 *, volatile unsigned __int128 *, int); 508 512 #endif 513 forall(dtype T) T * __atomic_load_n(T * const volatile *, int); 514 forall(dtype T) void __atomic_load(T * const volatile *, T **, int); 509 515 510 516 _Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int); … … 543 549 _Bool __atomic_compare_exchange (volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128 *, _Bool, int, int); 544 550 #endif 551 forall(dtype T) _Bool __atomic_compare_exchange_n (T * volatile *, T **, T*, _Bool, int, int); 552 forall(dtype T) _Bool __atomic_compare_exchange (T * volatile *, T **, T**, _Bool, int, int); 545 553 546 554 void __atomic_store_n(volatile _Bool *, _Bool, int); … … 581 589 void __atomic_store(volatile unsigned __int128 *, unsigned __int128 *, int); 582 590 #endif 591 forall(dtype T) void __atomic_store_n(T * volatile *, T *, int); 592 forall(dtype T) void __atomic_store(T * volatile *, T **, int); 583 593 584 594 char __atomic_add_fetch (volatile char *, char, int); -
libcfa/src/Makefile.am
r6a9d4b4 r933f32f 74 74 75 75 prelude.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 ${@} 77 77 78 78 prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@ 79 79 ${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 ${@} 81 81 82 82 -
libcfa/src/Makefile.in
r6a9d4b4 r933f32f 926 926 927 927 prelude.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 ${@} 929 929 930 930 prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@ 931 931 ${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 ${@} 933 933 934 934 #---------------------------------------------------------------------------------------------------------------- -
libcfa/src/bits/containers.hfa
r6a9d4b4 r933f32f 186 186 187 187 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 ) { 189 189 return this.head != 0; 190 190 } … … 196 196 //----------------------------------------------------------------------------- 197 197 #ifdef __cforall 198 forall(dtype TYPE | sized(TYPE))198 forall(dtype TYPE) 199 199 #define T TYPE 200 200 #define __getter_t * [T * & next, T * & prev] ( T & ) … … 268 268 269 269 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 ) { 271 271 return this.head != 0; 272 272 } -
libcfa/src/concurrency/CtxSwitch-i386.S
r6a9d4b4 r933f32f 41 41 #define PC_OFFSET ( 2 * PTR_BYTE ) 42 42 43 .text43 .text 44 44 .align 2 45 .globl CtxSwitch 45 .globl CtxSwitch 46 .type CtxSwitch, @function 46 47 CtxSwitch: 47 48 … … 50 51 51 52 movl 4(%esp),%eax 52 53 // Save floating & SSE control words on the stack.54 55 sub $8,%esp56 stmxcsr 0(%esp) // 4 bytes57 fnstcw 4(%esp) // 2 bytes58 53 59 54 // Save volatile registers on the stack. … … 67 62 movl %esp,SP_OFFSET(%eax) 68 63 movl %ebp,FP_OFFSET(%eax) 69 // movl 4(%ebp),%ebx // save previous eip for debugger70 // movl %ebx,PC_OFFSET(%eax)71 64 72 65 // Copy the "to" context argument from the stack to register eax … … 74 67 // argument is now at 8 + 12 = 20(%esp) 75 68 76 movl 2 8(%esp),%eax69 movl 20(%esp),%eax 77 70 78 71 // Load new context from the "to" area. … … 87 80 popl %ebx 88 81 89 // Load floating & SSE control words from the stack.90 91 fldcw 4(%esp)92 ldmxcsr 0(%esp)93 add $8,%esp94 95 82 // Return to thread. 96 83 97 84 ret 85 .size CtxSwitch, .-CtxSwitch 98 86 99 87 // Local Variables: // -
libcfa/src/concurrency/CtxSwitch-x86_64.S
r6a9d4b4 r933f32f 39 39 #define SP_OFFSET ( 0 * PTR_BYTE ) 40 40 #define FP_OFFSET ( 1 * PTR_BYTE ) 41 #define PC_OFFSET ( 2 * PTR_BYTE )42 41 43 .text 42 //----------------------------------------------------------------------------- 43 // Regular context switch routine which enables switching from one context to anouther 44 .text 44 45 .align 2 45 .globl CtxSwitch 46 .globl CtxSwitch 47 .type CtxSwitch, @function 46 48 CtxSwitch: 47 48 // Save floating & SSE control words on the stack.49 50 subq $8,%rsp51 stmxcsr 0(%rsp) // 4 bytes52 fnstcw 4(%rsp) // 2 bytes53 49 54 50 // Save volatile registers on the stack. … … 78 74 popq %r15 79 75 80 // Load floating & SSE control words from the stack.81 82 fldcw 4(%rsp)83 ldmxcsr 0(%rsp)84 addq $8,%rsp85 86 76 // Return to thread. 87 77 88 78 ret 79 .size CtxSwitch, .-CtxSwitch 89 80 90 .text 81 //----------------------------------------------------------------------------- 82 // Stub used to create new stacks which are ready to be context switched to 83 .text 91 84 .align 2 92 .globl CtxInvokeStub 85 .globl CtxInvokeStub 86 .type CtxInvokeStub, @function 93 87 CtxInvokeStub: 94 88 movq %rbx, %rdi 95 89 jmp *%r12 90 .size CtxInvokeStub, .-CtxInvokeStub 96 91 97 92 // Local Variables: // -
libcfa/src/concurrency/coroutine.cfa
r6a9d4b4 r933f32f 35 35 36 36 extern "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__)); 42 44 } 43 45 … … 47 49 // minimum feasible stack size in bytes 48 50 #define MinStackSize 1000 49 static size_t pageSize = 0; // architecture pagesize HACK, should go in proper runtime singleton 51 extern size_t __page_size; // architecture pagesize HACK, should go in proper runtime singleton 52 53 void __stack_prepare( __stack_info_t * this, size_t create_size ); 50 54 51 55 //----------------------------------------------------------------------------- 52 56 // 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 } 57 void ?{}( __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 71 void ^?{}(__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 } 72 87 } 73 88 74 89 void ?{}( 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 79 80 81 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; 82 97 } 83 98 84 99 void ^?{}(coroutine_desc& this) { 85 86 coroutine_desc * src = TL_GET( this_coroutine );87 88 89 90 91 92 93 94 95 96 97 98 99 100 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 } 102 117 } 103 118 … … 106 121 forall(dtype T | is_coroutine(T)) 107 122 void 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 156 void __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; 190 182 } 191 183 … … 193 185 // is not inline (We can't inline Cforall in C) 194 186 extern "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 } 216 207 } 217 208 -
libcfa/src/concurrency/coroutine.hfa
r6a9d4b4 r933f32f 46 46 //----------------------------------------------------------------------------- 47 47 // Public coroutine API 48 static inline void suspend( );48 static inline void suspend(void); 49 49 50 50 forall(dtype T | is_coroutine(T)) 51 static inline voidresume(T & cor);51 static inline T & resume(T & cor); 52 52 53 53 forall(dtype T | is_coroutine(T)) … … 64 64 forall(dtype T | is_coroutine(T)) 65 65 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"); 66 70 } 67 71 68 72 // 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 74 static 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 94 extern void __stack_prepare ( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 71 95 72 96 // Suspend implementation inlined for performance 73 static inline void suspend( ) {97 static inline void suspend(void) { 74 98 // optimization : read TLS once and reuse it 75 99 // Safety note: this is preemption safe since if … … 77 101 // will also migrate which means this value will 78 102 // stay in syn with the TLS 79 coroutine_desc * src = TL_GET( this_ coroutine );103 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 80 104 81 105 assertf( src->last != 0, … … 93 117 // Resume implementation inlined for performance 94 118 forall(dtype T | is_coroutine(T)) 95 static inline voidresume(T & cor) {119 static inline T & resume(T & cor) { 96 120 // optimization : read TLS once and reuse it 97 121 // Safety note: this is preemption safe since if … … 99 123 // will also migrate which means this value will 100 124 // stay in syn with the TLS 101 coroutine_desc * src = TL_GET( this_ coroutine );125 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 102 126 coroutine_desc * dst = get_coroutine(cor); 103 127 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); 106 130 CtxStart(&cor, CtxInvokeCoroutine); 107 131 } … … 121 145 // always done for performance testing 122 146 CoroutineCtxSwitch( src, dst ); 147 148 return cor; 123 149 } 124 150 … … 129 155 // will also migrate which means this value will 130 156 // stay in syn with the TLS 131 coroutine_desc * src = TL_GET( this_ coroutine );157 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 132 158 133 159 // not resuming self ? -
libcfa/src/concurrency/invoke.c
r6a9d4b4 r933f32f 28 28 29 29 extern void __suspend_internal(void); 30 extern void __leave_coroutine( void);31 extern void __finish_creation( void);30 extern void __leave_coroutine( struct coroutine_desc * ); 31 extern void __finish_creation( struct thread_desc * ); 32 32 extern void __leave_thread_monitor( struct thread_desc * this ); 33 33 extern void disable_interrupts(); … … 47 47 cor->state = Active; 48 48 49 enable_interrupts( __cfaabi_dbg_ctx );50 51 49 main( this ); 52 50 53 51 //Final suspend, should never return 54 __leave_coroutine( );52 __leave_coroutine( cor ); 55 53 __cabi_abort( "Resumed dead coroutine" ); 56 54 } … … 62 60 __attribute((__unused__)) struct _Unwind_Exception * unwind_exception, 63 61 __attribute((__unused__)) struct _Unwind_Context * context, 64 __attribute((__unused__))void * param62 void * param 65 63 ) { 66 64 if( actions & _UA_END_OF_STACK ) { 67 65 // We finished unwinding the coroutine, 68 66 // leave it 69 __leave_coroutine( );67 __leave_coroutine( param ); 70 68 __cabi_abort( "Resumed dead coroutine" ); 71 69 } … … 75 73 } 76 74 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);75 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) __attribute__ ((__noreturn__)); 76 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) { 77 _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, cor ); 80 78 printf("UNWIND ERROR %d after force unwind\n", ret); 81 79 abort(); … … 88 86 void *this 89 87 ) { 88 // Fetch the thread handle from the user defined thread structure 89 struct thread_desc* thrd = get_thread( this ); 90 90 91 // First suspend, once the thread arrives here, 91 92 // 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 ); 97 94 98 95 // Officially start the thread by enabling preemption … … 120 117 void (*invoke)(void *) 121 118 ) { 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; 123 121 124 122 #if defined( __i386 ) 125 123 126 124 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) 130 126 void *rturn; // where to go on return from uSwitch 131 void *dummyReturn; 132 void *argument[3]; 133 void *padding; 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 134 130 }; 135 131 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 fp132 cor->context.SP = (char *)stack->base - sizeof( struct FakeStack ); 133 cor->context.FP = NULL; // terminate stack with NULL fp 138 134 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-520143 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7135 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; 144 140 145 141 #elif defined( __x86_64 ) … … 147 143 struct FakeStack { 148 144 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)151 145 void *rturn; // where to go on return from uSwitch 152 146 void *dummyReturn; // NULL return address to provide proper alignment 153 147 }; 154 148 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 fp149 cor->context.SP = (char *)stack->base - sizeof( struct FakeStack ); 150 cor->context.FP = NULL; // terminate stack with NULL fp 157 151 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-520163 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7152 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; 164 158 165 159 #elif defined( __ARM_ARCH ) … … 171 165 }; 172 166 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; 175 169 176 struct FakeStack *fs = (struct FakeStack *) ((struct machine_context_t *)stack->context)->SP;170 struct FakeStack *fs = (struct FakeStack *)cor->context.SP; 177 171 178 172 fs->intRegs[8] = CtxInvokeStub; -
libcfa/src/concurrency/invoke.h
r6a9d4b4 r933f32f 50 50 51 51 extern thread_local struct KernelThreadData { 52 struct coroutine_desc * volatile this_coroutine;53 52 struct thread_desc * volatile this_thread; 54 53 struct processor * volatile this_processor; … … 61 60 } kernelTLS __attribute__ ((tls_model ( "initial-exec" ))); 62 61 } 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 ); } // UNSAFE67 62 #endif 68 63 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; 77 93 }; 78 94 … … 80 96 81 97 struct coroutine_desc { 98 // context that is switch during a CtxSwitch 99 struct __stack_context_t context; 100 82 101 // stack information of the coroutine 83 struct coStack_t stack;84 85 // textual name for coroutine/task , initialized by uC++ generated code102 struct __stack_info_t stack; 103 104 // textual name for coroutine/task 86 105 const char * name; 87 88 // copy of global UNIX variable errno89 int errno_;90 106 91 107 // current execution status for coroutine 92 108 enum coroutine_state state; 109 93 110 // first coroutine to resume this one 94 111 struct coroutine_desc * starter; … … 144 161 struct thread_desc { 145 162 // 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 146 171 // coroutine body used to store context 147 172 struct coroutine_desc self_cor; … … 170 195 struct thread_desc * prev; 171 196 } 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 176 205 static inline thread_desc * & get_next( thread_desc & this ) { 177 206 return this.next; … … 231 260 // assembler routines that performs the context switch 232 261 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"); 253 265 254 266 #endif //_INVOKE_PRIVATE_H_ -
libcfa/src/concurrency/kernel.cfa
r6a9d4b4 r933f32f 36 36 #include "invoke.h" 37 37 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 //----------------------------------------------------------------------------- 38 107 //Start and stop routine for the kernel, declared first to make sure they run first 39 108 static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); … … 42 111 //----------------------------------------------------------------------------- 43 112 // Kernel storage 44 KERNEL_STORAGE(cluster, 45 KERNEL_STORAGE(processor, 46 KERNEL_STORAGE(thread_desc, 47 KERNEL_STORAGE( machine_context_t,mainThreadCtx);113 KERNEL_STORAGE(cluster, mainCluster); 114 KERNEL_STORAGE(processor, mainProcessor); 115 KERNEL_STORAGE(thread_desc, mainThread); 116 KERNEL_STORAGE(__stack_t, mainThreadCtx); 48 117 49 118 cluster * mainCluster; … … 54 123 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters; 55 124 } 125 126 size_t __page_size = 0; 56 127 57 128 //----------------------------------------------------------------------------- … … 60 131 NULL, 61 132 NULL, 62 NULL,63 133 { 1, false, false } 64 134 }; … … 67 137 // Struct to steal stack 68 138 struct current_stack_info_t { 69 machine_context_t ctx; 70 unsigned int size; // size of stack 139 __stack_t * storage; // pointer to stack object 71 140 void *base; // base of stack 72 void *storage; // pointer to stack73 141 void *limit; // stack grows towards stack limit 74 142 void *context; // address of cfa_context_t 75 void *top; // address of top of storage76 143 }; 77 144 78 145 void ?{}( 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; 82 149 83 150 rlimit r; 84 151 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); 88 155 this.context = &storage_mainThreadCtx; 89 this.top = this.base;90 156 } 91 157 92 158 //----------------------------------------------------------------------------- 93 159 // 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 }103 160 104 161 void ?{}( 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; 106 169 name = "Main Thread"; 107 errno_ = 0;108 170 state = Start; 109 171 starter = NULL; 172 last = NULL; 173 cancellation = NULL; 110 174 } 111 175 112 176 void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) { 177 state = Start; 113 178 self_cor{ info }; 114 179 curr_cor = &self_cor; … … 241 306 } 242 307 308 static int * __volatile_errno() __attribute__((noinline)); 309 static int * __volatile_errno() { asm(""); return &errno; } 310 243 311 // KERNEL ONLY 244 312 // runThread runs a thread by context switching 245 313 // from the processor coroutine to the target thread 246 static void runThread(processor * this, thread_desc * dst) { 247 assert(dst->curr_cor); 314 static void runThread(processor * this, thread_desc * thrd_dst) { 248 315 coroutine_desc * proc_cor = get_coroutine(this->runner); 249 coroutine_desc * thrd_cor = dst->curr_cor;250 316 251 317 // Reset the terminating actions here … … 253 319 254 320 // 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; 260 335 } 261 336 … … 263 338 static void returnToKernel() { 264 339 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; 267 363 } 268 364 … … 307 403 processor * proc = (processor *) arg; 308 404 kernelTLS.this_processor = proc; 309 kernelTLS.this_coroutine = NULL;310 405 kernelTLS.this_thread = NULL; 311 406 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1]; … … 314 409 // to waste the perfectly valid stack create by pthread. 315 410 current_stack_info_t info; 316 machine_context_t ctx;317 info. context= &ctx;411 __stack_t ctx; 412 info.storage = &ctx; 318 413 (proc->runner){ proc, &info }; 319 414 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); 321 416 322 417 //Set global state 323 kernelTLS.this_coroutine = get_coroutine(proc->runner);324 418 kernelTLS.this_thread = NULL; 325 419 … … 350 444 351 445 // KERNEL_ONLY 352 void kernel_first_resume( processor * this) {353 coroutine_desc * src = kernelTLS.this_coroutine;446 void kernel_first_resume( processor * this ) { 447 thread_desc * src = mainThread; 354 448 coroutine_desc * dst = get_coroutine(this->runner); 355 449 356 450 verify( ! kernelTLS.preemption_state.enabled ); 357 451 358 create_stack(&dst->stack, dst->stack.size);452 __stack_prepare( &dst->stack, 65000 ); 359 453 CtxStart(&this->runner, CtxInvokeCoroutine); 360 454 361 455 verify( ! kernelTLS.preemption_state.enabled ); 362 456 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; 365 459 366 460 // set state of current coroutine to inactive 367 461 src->state = src->state == Halted ? Halted : Inactive; 368 462 369 // set new coroutine that task is executing370 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 will376 // stay disabled.377 disable_interrupts();378 379 463 // 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 ); 382 466 // when CtxSwitch returns we are back in the src coroutine 383 467 … … 386 470 387 471 verify( ! kernelTLS.preemption_state.enabled ); 472 } 473 474 // KERNEL_ONLY 475 void 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 ); 388 485 } 389 486 … … 394 491 void ScheduleThread( thread_desc * thrd ) { 395 492 verify( thrd ); 396 verify( thrd->s elf_cor.state != Halted );493 verify( thrd->state != Halted ); 397 494 398 495 verify( ! kernelTLS.preemption_state.enabled ); … … 551 648 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 552 649 650 __page_size = sysconf( _SC_PAGESIZE ); 651 553 652 __cfa_dbg_global_clusters.list{ __get }; 554 653 __cfa_dbg_global_clusters.lock{}; … … 565 664 mainThread = (thread_desc *)&storage_mainThread; 566 665 current_stack_info_t info; 666 info.storage = (__stack_t*)&storage_mainThreadCtx; 567 667 (*mainThread){ &info }; 568 668 … … 599 699 kernelTLS.this_processor = mainProcessor; 600 700 kernelTLS.this_thread = mainThread; 601 kernelTLS.this_coroutine = &mainThread->self_cor;602 701 603 702 // Enable preemption … … 634 733 // which is currently here 635 734 __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE); 636 returnToKernel();735 kernel_last_resume( kernelTLS.this_processor ); 637 736 mainThread->self_cor.state = Halted; 638 737 … … 720 819 __cfaabi_dbg_bits_write( abort_text, len ); 721 820 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 ); 724 823 __cfaabi_dbg_bits_write( abort_text, len ); 725 824 } -
libcfa/src/concurrency/thread.cfa
r6a9d4b4 r933f32f 31 31 // Thread ctors and dtors 32 32 void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) { 33 context{ NULL, NULL }; 33 34 self_cor{ name, storage, storageSize }; 34 verify(&self_cor);35 state = Start; 35 36 curr_cor = &self_cor; 36 37 self_mon.owner = &this; … … 73 74 forall( dtype T | is_thread(T) ) 74 75 void __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 ); 80 78 81 79 disable_interrupts(); 82 create_stack(&thrd_c->stack, thrd_c->stack.size);83 kernelTLS.this_coroutine = thrd_c;84 80 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 ); 87 84 88 ScheduleThread(th rd_h);85 ScheduleThread(this_thrd); 89 86 enable_interrupts( __cfaabi_dbg_ctx ); 90 87 } … … 92 89 extern "C" { 93 90 // 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 ); 97 97 } 98 98 } … … 112 112 } 113 113 114 // KERNEL ONLY115 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {116 // set state of current coroutine to inactive117 src->state = src->state == Halted ? Halted : Inactive;118 dst->state = Active;119 120 // set new coroutine that the processor is executing121 // and context switch to it122 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 active128 dst->state = dst->state == Halted ? Halted : Inactive;129 src->state = Active;130 }131 132 114 // Local Variables: // 133 115 // mode: c // -
libcfa/src/concurrency/thread.hfa
r6a9d4b4 r933f32f 61 61 void ^?{}(thread_desc & this); 62 62 63 static inline void ?{}(thread_desc & this) { this{ "Anonymous Thread", *mainCluster, NULL, 0 }; }63 static inline void ?{}(thread_desc & this) { this{ "Anonymous Thread", *mainCluster, NULL, 65000 }; } 64 64 static inline void ?{}(thread_desc & this, size_t stackSize ) { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; } 65 65 static 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 }; }66 static inline void ?{}(thread_desc & this, struct cluster & cl ) { this{ "Anonymous Thread", cl, NULL, 65000 }; } 67 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize ) { this{ "Anonymous Thread", cl, NULL, stackSize }; } 68 68 static 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 }; }69 static inline void ?{}(thread_desc & this, const char * const name) { this{ name, *mainCluster, NULL, 65000 }; } 70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl ) { this{ name, cl, NULL, 65000 }; } 71 71 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; } 72 72 -
libcfa/src/containers/maybe.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 24 15:40:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jul 20 15:23:50 201713 // Update Count : 212 // Last Modified On : Sun Feb 17 11:22:03 2019 13 // Update Count : 3 14 14 // 15 15 … … 39 39 forall(otype T) 40 40 maybe(T) ?=?(maybe(T) & this, maybe(T) that) { 41 if (this.has_value & that.has_value) {41 if (this.has_value && that.has_value) { 42 42 this.value = that.value; 43 43 } else if (this.has_value) { -
libcfa/src/containers/result.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 24 15:40:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jul 20 15:23:58 201713 // Update Count : 212 // Last Modified On : Sun Feb 17 11:24:04 2019 13 // Update Count : 3 14 14 // 15 15 … … 48 48 forall(otype T, otype E) 49 49 result(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) { 51 51 this.value = that.value; 52 52 } else if (this.has_value) { -
libcfa/src/fstream.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 24 18:33:38 201813 // Update Count : 3 0412 // Last Modified On : Thu May 16 08:33:28 2019 13 // Update Count : 328 14 14 // 15 15 … … 23 23 #include <complex.h> // creal, cimag 24 24 #include <assert.h> 25 #include <errno.h> // errno 25 26 26 27 #define IO_MSG "I/O error: " 27 28 28 void ?{}( ofstream & os, void * file , bool sepDefault, bool sepOnOff, bool nlOnOff, bool prt, const char * separator, const char * tupleSeparator) {29 void ?{}( ofstream & os, void * file ) { 29 30 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, " " ); 35 37 sepSetCur( os, sepGet( os ) ); 36 sepSetTuple( os, tupleSeparator);38 sepSetTuple( os, ", " ); 37 39 } 38 40 … … 102 104 103 105 void open( ofstream & os, const char * name, const char * mode ) { 104 FILE * file = fopen( name, mode );106 FILE * file = fopen( name, mode ); 105 107 #ifdef __CFA_DEBUG__ 106 108 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 ) ); 110 110 } // if 111 111 #endif // __CFA_DEBUG__ 112 (os){ file , true, false, true, false, " ", ", "};112 (os){ file }; 113 113 } // open 114 114 … … 121 121 122 122 if ( fclose( (FILE *)(os.file) ) == EOF ) { 123 perror( IO_MSG "close output");123 abort( IO_MSG "close output %s", strerror( errno ) ); 124 124 } // if 125 125 } // close … … 127 127 ofstream & write( ofstream & os, const char * data, size_t size ) { 128 128 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" ); 131 130 } // if 132 131 133 132 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 ) ); 136 134 } // if 137 135 return os; … … 144 142 if ( len == EOF ) { 145 143 if ( ferror( (FILE *)(os.file) ) ) { 146 fprintf( stderr, "invalid write\n" ); 147 exit( EXIT_FAILURE ); 144 abort( "invalid write\n" ); 148 145 } // if 149 146 } // if … … 155 152 } // fmt 156 153 157 static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_) , true, false, true, false, " ", ", "};154 static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_) }; 158 155 ofstream & sout = soutFile; 159 static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_) , true, false, true, false, " ", ", "};156 static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_) }; 160 157 ofstream & serr = serrFile; 161 158 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 164 void nl( ofstream & os ) { 165 if ( getANL( os ) ) (ofstream &)(nl( os )); // implementation only 166 else setPrt( os, false ); // turn off 167 } 162 168 163 169 //--------------------------------------- … … 166 172 void ?{}( ifstream & is, void * file ) { 167 173 is.file = file; 174 is.nlOnOff = false; 168 175 } 169 176 … … 177 184 open( is, name, "r" ); 178 185 } 186 187 void nlOn( ifstream & os ) { os.nlOnOff = true; } 188 void nlOff( ifstream & os ) { os.nlOnOff = false; } 189 bool getANL( ifstream & os ) { return os.nlOnOff; } 179 190 180 191 int fail( ifstream & is ) { … … 187 198 188 199 void open( ifstream & is, const char * name, const char * mode ) { 189 FILE * file = fopen( name, mode );200 FILE * file = fopen( name, mode ); 190 201 #ifdef __CFA_DEBUG__ 191 202 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 ) ); 195 204 } // if 196 205 #endif // __CFA_DEBUG__ … … 206 215 207 216 if ( fclose( (FILE *)(is.file) ) == EOF ) { 208 perror( IO_MSG "close input");217 abort( IO_MSG "close input %s", strerror( errno ) ); 209 218 } // if 210 219 } // close … … 212 221 ifstream & read( ifstream & is, char * data, size_t size ) { 213 222 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" ); 216 224 } // if 217 225 218 226 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 ) ); 221 228 } // if 222 229 return is; … … 225 232 ifstream &ungetc( ifstream & is, char c ) { 226 233 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" ); 229 235 } // if 230 236 231 237 if ( ungetc( c, (FILE *)(is.file) ) == EOF ) { 232 perror( IO_MSG "ungetc" ); 233 exit( EXIT_FAILURE ); 238 abort( IO_MSG "ungetc %s", strerror( errno ) ); 234 239 } // if 235 240 return is; … … 243 248 if ( len == EOF ) { 244 249 if ( ferror( (FILE *)(is.file) ) ) { 245 fprintf( stderr, "invalid read\n" ); 246 exit( EXIT_FAILURE ); 250 abort( "invalid read\n" ); 247 251 } // if 248 252 } // if -
libcfa/src/fstream.hfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 24 18:33:41 201813 // Update Count : 1 4912 // Last Modified On : Thu May 16 08:34:10 2019 13 // Update Count : 157 14 14 // 15 15 … … 70 70 extern ofstream & sout, & serr; 71 71 72 // extern ofstream & sout, & serr, & sexit, & sabort; 73 // void nl( ofstream & os ); 74 72 75 73 76 struct ifstream { 74 77 void * file; 78 bool nlOnOff; 75 79 }; // ifstream 76 80 77 81 // public 82 void nlOn( ifstream & ); 83 void nlOff( ifstream & ); 84 bool getANL( ifstream & ); 78 85 int fail( ifstream & is ); 79 86 int eof( ifstream & is ); -
libcfa/src/gmp.hfa
r6a9d4b4 r933f32f 10 10 // Created On : Tue Apr 19 08:43:43 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 4 23:25:51 201813 // Update Count : 2 212 // Last Modified On : Sat Apr 20 09:01:52 2019 13 // Update Count : 24 14 14 // 15 15 … … 271 271 272 272 void ?|?( ostype & os, Int mp ) { 273 (ostype)(os | mp); if ( getANL( os ) )nl( os );273 (ostype)(os | mp); nl( os ); 274 274 } // ?|? 275 275 } // distribution -
libcfa/src/heap.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Sep 6 09:01:30 201813 // Update Count : 51 312 // Last Modified On : Thu May 9 16:29:12 2019 13 // Update Count : 516 14 14 // 15 15 … … 220 220 StackLF<Storage> freeList; 221 221 #else 222 #error undefined lock type for bucket lock222 #error undefined lock type for bucket lock 223 223 #endif // SPINLOCK 224 224 size_t blockSize; // size of allocations on this list … … 234 234 }; // HeapManager 235 235 236 236 237 static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; } 238 237 239 // statically allocated variables => zero filled. 238 239 240 240 static size_t pageSize; // architecture pagesize 241 241 static size_t heapExpand; // sbrk advance … … 306 306 sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment 307 307 heapBegin = heapEnd = sbrk( 0 ); // get new start point 308 308 } // HeapManager 309 309 310 310 … … 316 316 // } // if 317 317 #endif // __STATISTICS__ 318 318 } // ~HeapManager 319 319 320 320 … … 533 533 534 534 static inline void * doMalloc( size_t size ) with ( heapManager ) { 535 HeapManager.Storage * block; 535 HeapManager.Storage * block; // pointer to new block of storage 536 536 537 537 // Look up size in the size list. Make sure the user request includes space for the header that must be allocated … … 656 656 __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST ); 657 657 if ( traceHeap() ) { 658 char helpText[64]; 658 enum { BufferSize = 64 }; 659 char helpText[BufferSize]; 659 660 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size ); 660 661 __cfaabi_dbg_bits_write( helpText, len ); … … 853 854 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 854 855 if ( ! mapped ) 855 856 #endif // __CFA_DEBUG__ 856 857 memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part 857 858 header->kind.real.blockSize |= 2; // mark new request as zero fill … … 1034 1035 // Local Variables: // 1035 1036 // tab-width: 4 // 1036 // compile-command: "cfa -nodebug -O2 heap.c " //1037 // compile-command: "cfa -nodebug -O2 heap.cfa" // 1037 1038 // End: // -
libcfa/src/iostream.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 24 18:33:40 201813 // Update Count : 58912 // Last Modified On : Sun May 19 10:48:27 2019 13 // Update Count : 654 14 14 // 15 15 … … 23 23 extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); 24 24 #include <float.h> // DBL_DIG, LDBL_DIG 25 #include <math.h> // isfinite 25 26 #include <complex.h> // creal, cimag 26 27 } 27 28 28 29 forall( 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 29 48 ostype & ?|?( ostype & os, bool b ) { 30 49 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); … … 135 154 } // ?|? 136 155 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 137 163 ostype & ?|?( ostype & os, float f ) { 138 164 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 140 169 return os; 141 170 } // ?|? … … 146 175 ostype & ?|?( ostype & os, double d ) { 147 176 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 149 181 return os; 150 182 } // ?|? … … 155 187 ostype & ?|?( ostype & os, long double ld ) { 156 188 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 158 193 return os; 159 194 } // ?|? … … 164 199 ostype & ?|?( ostype & os, float _Complex fc ) { 165 200 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" ); 167 212 return os; 168 213 } // ?|? … … 173 218 ostype & ?|?( ostype & os, double _Complex dc ) { 174 219 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" ); 176 231 return os; 177 232 } // ?|? … … 182 237 ostype & ?|?( ostype & os, long double _Complex ldc ) { 183 238 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" ); 185 250 return os; 186 251 } // ?|? … … 378 443 379 444 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 381 452 return is; 382 453 } // ?|? … … 470 541 } // ?|? 471 542 472 473 543 // manipulators 474 544 istype & ?|?( istype & is, istype & (* manip)( istype & ) ) { … … 477 547 478 548 istype & nl( istype & is ) { 479 fmt( is, "%*[ \t\f\n\r\v]" ); // ignore whitespace549 fmt( is, "%*[^\n]" ); // ignore characters to newline 480 550 return is; 481 551 } // 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 482 562 } // distribution 483 563 -
libcfa/src/iostream.hfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 24 18:33:40 201813 // Update Count : 2 2012 // Last Modified On : Sat May 11 10:31:27 2019 13 // Update Count : 232 14 14 // 15 15 … … 48 48 void close( ostype & os ); 49 49 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) )); 51 51 }; // ostream 52 52 … … 62 62 63 63 forall( 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 64 69 ostype & ?|?( ostype &, bool ); 65 70 void ?|?( ostype &, bool ); … … 144 149 145 150 trait istream( dtype istype ) { 151 void nlOn( istype & ); // read newline 152 void nlOff( istype & ); // scan newline 153 bool getANL( istype & ); // get scan newline (on/off) 146 154 int fail( istype & ); 147 155 int eof( istype & ); … … 150 158 istype & read( istype &, char *, size_t ); 151 159 istype & ungetc( istype &, char ); 152 int fmt( istype &, const char format[], ... ) ;160 int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); 153 161 }; // istream 154 162 … … 184 192 istype & ?|?( istype &, istype & (*)( istype & ) ); 185 193 istype & nl( istype & is ); 194 istype & nlOn( istype & ); 195 istype & nlOff( istype & ); 186 196 } // distribution 187 197 … … 205 215 206 216 // Local Variables: // 207 // mode: c //208 217 // tab-width: 4 // 209 218 // End: // -
libcfa/src/rational.cfa
r6a9d4b4 r933f32f 10 10 // Created On : Wed Apr 6 17:54:28 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 23 22:56:49 201813 // Update Count : 1 7012 // Last Modified On : Thu Mar 28 17:33:03 2019 13 // Update Count : 181 14 14 // 15 15 … … 35 35 static RationalImpl simplify( RationalImpl & n, RationalImpl & d ) { 36 36 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" ); 39 38 } // exit 40 39 if ( d < (RationalImpl){0} ) { d = -d; n = -n; } // move sign to numerator … … 54 53 void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) { 55 54 RationalImpl t = simplify( n, d ); // simplify 56 r.numerator = n / t; 57 r.denominator = d / t; 55 r.[numerator, denominator] = [n / t, d / t]; 58 56 } // rational 59 57 … … 78 76 RationalImpl prev = r.numerator; 79 77 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]; 82 79 return prev; 83 80 } // numerator … … 86 83 RationalImpl prev = r.denominator; 87 84 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]; 90 86 return prev; 91 87 } // denominator … … 120 116 121 117 Rational(RationalImpl) +?( Rational(RationalImpl) r ) { 122 Rational(RationalImpl) t = { r.numerator, r.denominator }; 123 return t; 118 return (Rational(RationalImpl)){ r.numerator, r.denominator }; 124 119 } // +? 125 120 126 121 Rational(RationalImpl) -?( Rational(RationalImpl) r ) { 127 Rational(RationalImpl) t = { -r.numerator, r.denominator }; 128 return t; 122 return (Rational(RationalImpl)){ -r.numerator, r.denominator }; 129 123 } // -? 130 124 131 125 Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 132 126 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 }; 135 128 } 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 }; 138 130 } // if 139 131 } // ?+? … … 141 133 Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 142 134 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 }; 145 136 } 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 }; 148 138 } // if 149 139 } // ?-? 150 140 151 141 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 }; 154 143 } // ?*? 155 144 156 145 Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 157 146 if ( r.numerator < (RationalImpl){0} ) { 158 r.numerator = -r.numerator; 159 r.denominator = -r.denominator; 147 r.[numerator, denominator] = [-r.numerator, -r.denominator]; 160 148 } // 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 }; 163 150 } // ?/? 164 151 … … 167 154 forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } ) 168 155 istype & ?|?( istype & is, Rational(RationalImpl) & r ) { 169 RationalImpl t;170 156 is | r.numerator | r.denominator; 171 t = simplify( r.numerator, r.denominator );157 RationalImpl t = simplify( r.numerator, r.denominator ); 172 158 r.numerator /= t; 173 159 r.denominator /= t; … … 185 171 } // distribution 186 172 } // distribution 173 174 forall( otype RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } ) 175 Rational(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 } 187 182 188 183 // conversion -
libcfa/src/rational.hfa
r6a9d4b4 r933f32f 12 12 // Created On : Wed Apr 6 17:56:25 2016 13 13 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Tue Dec 4 23:07:46 201815 // Update Count : 10 614 // Last Modified On : Tue Mar 26 23:16:10 2019 15 // Update Count : 109 16 16 // 17 17 … … 98 98 } // distribution 99 99 100 forall( otype RationalImpl | arithmetic( RationalImpl ) |{RationalImpl ?\?( RationalImpl, unsigned long );} ) 101 Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y ); 102 100 103 // conversion 101 104 forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } ) -
libcfa/src/stdhdr/stdbool.h
r6a9d4b4 r933f32f 10 10 // Created On : Mon Jul 4 23:25:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jul 5 20:39:51 201613 // Update Count : 1 212 // Last Modified On : Mon Mar 25 08:00:08 2019 13 // Update Count : 15 14 14 // 15 15 16 16 extern "C" { 17 17 #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 18 29 } // extern "C" 19 30 -
libcfa/src/stdlib.hfa
r6a9d4b4 r933f32f 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 17 15:37:45 201813 // Update Count : 3 4612 // Last Modified On : Wed Apr 24 17:35:43 2019 13 // Update Count : 352 14 14 // 15 15 … … 40 40 } // malloc 41 41 42 // T & malloc( void ) {43 // int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc44 // printf( "& malloc %p\n", &p );45 // return p;46 // // return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc47 // } // malloc48 49 42 T * calloc( size_t dim ) { 50 43 return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc … … 76 69 T * alloc( char fill ) { 77 70 T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 78 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initialwith fill value71 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initialize with fill value 79 72 } // alloc 80 73 … … 84 77 85 78 T * alloc( size_t dim, char fill ) { 86 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc87 return (T *)memset( ptr, (int)fill, dim * sizeof(T) ); // initialwith fill value79 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 88 81 } // alloc 89 82 -
libcfa/src/time.hfa
r6a9d4b4 r933f32f 30 30 31 31 static inline { 32 Duration ?=?( Duration & dur, zero_t ) { return dur{ 0 }; }32 Duration ?=?( Duration & dur, __attribute__((unused)) zero_t ) { return dur{ 0 }; } 33 33 34 34 Duration +?( Duration rhs ) with( rhs ) { return (Duration)@{ +tv }; } … … 59 59 bool ?>=?( Duration lhs, Duration rhs ) { return lhs.tv >= rhs.tv; } 60 60 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; } 67 67 68 68 Duration abs( Duration rhs ) { return rhs.tv >= 0 ? rhs : -rhs; } … … 101 101 void ?{}( timeval & t, time_t sec, suseconds_t usec ) { t.tv_sec = sec; t.tv_usec = usec; } 102 102 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 }; } 106 106 timeval ?+?( timeval lhs, timeval rhs ) { return (timeval)@{ lhs.tv_sec + rhs.tv_sec, lhs.tv_usec + rhs.tv_usec }; } 107 107 timeval ?-?( timeval lhs, timeval rhs ) { return (timeval)@{ lhs.tv_sec - rhs.tv_sec, lhs.tv_usec - rhs.tv_usec }; } … … 116 116 void ?{}( timespec & t, time_t sec, __syscall_slong_t nsec ) { t.tv_sec = sec; t.tv_nsec = nsec; } 117 117 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 }; } 121 121 timespec ?+?( timespec lhs, timespec rhs ) { return (timespec)@{ lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec }; } 122 122 timespec ?-?( timespec lhs, timespec rhs ) { return (timespec)@{ lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec }; } … … 145 145 void ?{}( Time & time, int year, int month = 0, int day = 0, int hour = 0, int min = 0, int sec = 0, int nsec = 0 ); 146 146 static inline { 147 Time ?=?( Time & time, zero_t ) { return time{ 0 }; }147 Time ?=?( Time & time, __attribute__((unused)) zero_t ) { return time{ 0 }; } 148 148 149 149 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 24 24 25 25 static inline void ?{}( Duration & dur ) with( dur ) { tv = 0; } 26 static inline void ?{}( Duration & dur, zero_t ) with( dur ) { tv = 0; }26 static inline void ?{}( Duration & dur, __attribute__((unused)) zero_t ) with( dur ) { tv = 0; } 27 27 28 28 … … 34 34 35 35 static inline void ?{}( Time & time ) with( time ) { tv = 0; } 36 static inline void ?{}( Time & time, zero_t ) with( time ) { tv = 0; }36 static inline void ?{}( Time & time, __attribute__((unused)) zero_t ) with( time ) { tv = 0; } 37 37 38 38 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.