Changes in / [eb7f20c:41fcd94]
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/papers/general/Paper.tex
reb7f20c r41fcd94 2 2 3 3 \usepackage{fullpage} 4 \usepackage{epic,eepic} 4 5 \usepackage{xspace,calc,comment} 5 6 \usepackage{upquote} % switch curled `'" to straight … … 36 37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 38 38 \newcommand{\Textbf}[ 1]{{\color{red}\textbf{#1}}}39 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} 39 40 \newcommand{\TODO}[1]{\textbf{TODO}: {\itshape #1}} % TODO included 40 41 %\newcommand{\TODO}[1]{} % TODO elided … … 1052 1053 \label{s:WithClauseStatement} 1053 1054 1054 Grouping heterogenous data into \newterm{aggregate}s is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:1055 \begin{cfa} 1056 struct S { $\C{// aggregate}$1057 char c; $\C{// fields}$1055 Grouping heterogenous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers: 1056 \begin{cfa} 1057 struct S { $\C{// aggregate}$ 1058 char c; $\C{// fields}$ 1058 1059 int i; 1059 1060 double d; … … 1061 1062 S s, as[10]; 1062 1063 \end{cfa} 1063 However, routines manipulating aggregates have repeition ofthe aggregate name to access its containing fields:1064 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields: 1064 1065 \begin{cfa} 1065 1066 void f( S s ) { 1066 `s.`c; `s.`i; `s.`d; $\C{// access containing fields}$1067 `s.`c; `s.`i; `s.`d; $\C{// access containing fields}$ 1067 1068 } 1068 1069 \end{cfa} … … 1070 1071 \begin{C++} 1071 1072 class C { 1072 char c; $\C{// fields}$1073 char c; $\C{// fields}$ 1073 1074 int i; 1074 1075 double d; 1075 int mem() { $\C{// implicit "this" parameter}$1076 `this->`c; `this->`i; `this->`d; $\C{// access containing fields}$1076 int mem() { $\C{// implicit "this" parameter}$ 1077 `this->`c; `this->`i; `this->`d; $\C{// access containing fields}$ 1077 1078 } 1078 1079 } 1079 1080 \end{C++} 1080 Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of nested lexical-scoping. 1081 Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping. 1082 However, for other aggregate parameters, qualification is necessary: 1083 \begin{cfa} 1084 struct T { double m, n; }; 1085 int C::mem( T & t ) { $\C{// multiple aggregate parameters}$ 1086 c; i; d; $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$ 1087 `t.`m; `t.`n; $\C{// must qualify}$ 1088 } 1089 \end{cfa} 1081 1090 1082 1091 % In object-oriented programming, there is an implicit first parameter, often names @self@ or @this@, which is elided. … … 1088 1097 % \TODO{Fill out section. Be sure to mention arbitrary expressions in with-blocks, recent change driven by Thierry to prioritize field name over parameters.} 1089 1098 1090 \CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containingfield identifiers.1091 Hence, the qualified fields become variables , and making it easier to optimizefield references in a block.1092 \begin{cfa} 1093 void f( S s ) `with( s )` { $\C{// with clause}$1094 c; i; d; $\C{\color{red}// s.c, s.i, s.d}$1099 To simplify the programmer experience, \CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers. 1100 Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block. 1101 \begin{cfa} 1102 void f( S s ) `with( s )` { $\C{// with clause}$ 1103 c; i; d; $\C{\color{red}// s.c, s.i, s.d}$ 1095 1104 } 1096 1105 \end{cfa} … … 1098 1107 \begin{cfa} 1099 1108 int mem( S & this ) `with( this )` { $\C{// with clause}$ 1100 c; i; d; $\C{\color{red}// this.c, this.i, this.d}$ 1101 } 1102 \end{cfa} 1103 The key generality over the object-oriented approach is that one aggregate parameter \lstinline[language=C++]@this@ is not treated specially over other aggregate parameters: 1104 \begin{cfa} 1105 struct T { double m, n; }; 1109 c; i; d; $\C{\color{red}// this.c, this.i, this.d}$ 1110 } 1111 \end{cfa} 1112 with the generality of opening multiple aggregate-parameters: 1113 \begin{cfa} 1106 1114 int mem( S & s, T & t ) `with( s, t )` { $\C{// multiple aggregate parameters}$ 1107 c; i; d; $\C{\color{red}// s.c, s.i, s.d}$ 1108 m; n; $\C{\color{red}// t.m, t.n}$ 1109 } 1110 \end{cfa} 1111 The equivalent object-oriented style is: 1112 \begin{cfa} 1113 int S::mem( T & t ) { $\C{// multiple aggregate parameters}$ 1114 c; i; d; $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$ 1115 `t.`m; `t.`n; 1115 c; i; d; $\C{\color{red}// s.c, s.i, s.d}$ 1116 m; n; $\C{\color{red}// t.m, t.n}$ 1117 } 1118 \end{cfa} 1119 1120 In detail, the @with@ clause/statement has the form: 1121 \begin{cfa} 1122 $\emph{with-statement}$: 1123 'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$ 1124 \end{cfa} 1125 and may appear as the body of a routine or nested within a routine body. 1126 Each expression in the expression-list provides a type and object. 1127 The type must be an aggregate type. 1128 (Enumerations are already opened.) 1129 The object is the implicit qualifier for the open structure-fields. 1130 1131 All expressions in the expression list are open in ``parallel'' within the compound statement. 1132 This semantic is different from Pascal, which nests the openings. 1133 The difference between parallel and nesting occurs for fields with the same name but different type: 1134 \begin{cfa} 1135 struct S { int i; int j; double m; } s, w; 1136 struct T { int i; int k; int m } t, w; 1137 with( s, t ) { 1138 j + k; $\C{// unambiguous, s.j + t.m}$ 1139 m = 5.0; $\C{// unambiguous, t.m = 5.0}$ 1140 m = 1; $\C{// unambiguous, s.m = 1}$ 1141 int a = s.i + m; $\C{// unambiguous, a = s.i + t.i}$ 1142 int b = s.i + t.i; $\C{// unambiguous, qualification}$ 1143 sout | (double)m | endl; $\C{// unambiguous, cast}$ 1144 i; $\C{// ambiguous}$ 1145 } 1146 \end{cfa} 1147 \CFA's ability to overload variables means usages of field with the same names can be automatically disambiguated, eliminating most qualification. 1148 Qualification or a cast is used to disambiguate. 1149 A cast may be necessary to disambiguate between the overload variables in a @with@ expression: 1150 \begin{cfa} 1151 with( w ) { ... } $\C{// ambiguous, same name and no context}$ 1152 with( (S)w ) { ... } $\C{// unambiguous}$ 1153 \end{cfa} 1154 1155 \begin{cfa} 1156 struct S { int i, j; } sv; 1157 with( sv ) { 1158 S & sr = sv; 1159 with( sr ) { 1160 S * sp = &sv; 1161 with( *sp ) { 1162 i = 3; j = 4; $\C{\color{red}// sp-{\textgreater}i, sp-{\textgreater}j}$ 1163 } 1164 i = 3; j = 4; $\C{\color{red}// sr.i, sr.j}$ 1165 } 1166 i = 3; j = 4; $\C{\color{red}// sv.i, sv.j}$ 1116 1167 } 1117 1168 \end{cfa} … … 1122 1173 struct S1 { ... } s1; 1123 1174 struct S2 { ... } s2; 1124 `with( s1 )` { $\C{// with statement}$1175 `with( s1 )` { $\C{// with statement}$ 1125 1176 // access fields of s1 without qualification 1126 `with( s2 )` { $\C{// nesting}$1177 `with( s2 )` { $\C{// nesting}$ 1127 1178 // access fields of s1 and s2 without qualification 1128 1179 } … … 1134 1185 \end{cfa} 1135 1186 1136 When opening multiple structures, fields with the same name and type are ambiguous and must be fully qualified.1137 For fields with the same name but different type, context/cast can be used to disambiguate.1138 \begin{cfa}1139 struct S { int i; int j; double m; } a, c;1140 struct T { int i; int k; int m } b, c;1141 `with( a, b )` {1142 j + k; $\C{// unambiguous, unique names define unique types}$1143 i; $\C{// ambiguous, same name and type}$1144 a.i + b.i; $\C{// unambiguous, qualification defines unique names}$1145 m; $\C{// ambiguous, same name and no context to define unique type}$1146 m = 5.0; $\C{// unambiguous, same name and context defines unique type}$1147 m = 1; $\C{// unambiguous, same name and context defines unique type}$1148 }1149 `with( c )` { ... } $\C{// ambiguous, same name and no context}$1150 `with( (S)c )` { ... } $\C{// unambiguous, same name and cast defines unique type}$1151 \end{cfa}1152 1153 The components in the "with" clause1154 1155 with ( a, b, c ) { ... }1156 1157 serve 2 purposes: each component provides a type and object. The type must be a1158 structure type. Enumerations are already opened, and I think a union is opened1159 to some extent, too. (Or is that just unnamed unions?) The object is the target1160 that the naked structure-fields apply to. The components are open in "parallel"1161 at the scope of the "with" clause/statement, so opening "a" does not affect1162 opening "b", etc. This semantic is different from Pascal, which nests the1163 openings.1164 1165 Having said the above, it seems reasonable to allow a "with" component to be an1166 expression. The type is the static expression-type and the object is the result1167 of the expression. Again, the type must be an aggregate. Expressions require1168 parenthesis around the components.1169 1170 with( a, b, c ) { ... }1171 1172 Does this now make sense?1173 1174 Having written more CFA code, it is becoming clear to me that I *really* want1175 the "with" to be implemented because I hate having to type all those object1176 names for fields. It's a great way to drive people away from the language.1177 1178 1187 1179 1188 \subsection{Exception Handling ???} … … 1189 1198 1190 1199 \subsection{Alternative Declaration Syntax} 1200 1201 \newcommand{\R}[1]{\Textbf{#1}} 1202 \newcommand{\B}[1]{{\Textbf[blue]{#1}}} 1203 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} 1204 1205 C declaration syntax is notoriously confusing and error prone. 1206 For example, many C programmers are confused by a declaration as simple as: 1207 \begin{flushleft} 1208 \lstDeleteShortInline@% 1209 \begin{tabular}{@{}ll@{}} 1210 \begin{cfa} 1211 int * x[5] 1212 \end{cfa} 1213 & 1214 \raisebox{-0.75\totalheight}{\input{Cdecl}} 1215 \end{tabular} 1216 \lstMakeShortInline@% 1217 \end{flushleft} 1218 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers? 1219 The fact this declaration is unclear to many C programmers means there are productivity and safety issues even for basic programs. 1220 Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site. 1221 For example, a routine returning a pointer to an array of integers is defined and used in the following way: 1222 \begin{cfa} 1223 int `(*`f`())[`5`]` {...}; $\C{// definition}$ 1224 ... `(*`f`())[`3`]` += 1; $\C{// usage}$ 1225 \end{cfa} 1226 Essentially, the return type is wrapped around the routine name in successive layers (like an onion). 1227 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice. 1228 1229 \CFA provides its own type, variable and routine declarations, using a different syntax. 1230 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type. 1231 In the following example, \R{red} is the base type and \B{blue} is qualifiers. 1232 The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type. 1233 \begin{quote} 1234 \lstDeleteShortInline@% 1235 \lstset{moredelim=**[is][\color{blue}]{+}{+}} 1236 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1237 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1238 \begin{cfa} 1239 +[5] *+ `int` x1; 1240 +* [5]+ `int` x2; 1241 +[* [5] int]+ f`( int p )`; 1242 \end{cfa} 1243 & 1244 \begin{cfa} 1245 `int` +*+ x1 +[5]+; 1246 `int` +(*+x2+)[5]+; 1247 +int (*+f`( int p )`+)[5]+; 1248 \end{cfa} 1249 \end{tabular} 1250 \lstMakeShortInline@% 1251 \end{quote} 1252 The only exception is bit field specification, which always appear to the right of the base type. 1253 % Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter. 1254 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1255 For instance, variables ©x© and ©y© of type pointer to integer are defined in \CFA as follows: 1256 \begin{quote} 1257 \lstDeleteShortInline@% 1258 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1259 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1260 \begin{cfa} 1261 `*` int x, y; 1262 \end{cfa} 1263 & 1264 \begin{cfa} 1265 int `*`x, `*`y; 1266 \end{cfa} 1267 \end{tabular} 1268 \lstMakeShortInline@% 1269 \end{quote} 1270 The downside of this semantics is the need to separate regular and pointer declarations: 1271 \begin{quote} 1272 \lstDeleteShortInline@% 1273 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1274 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1275 \begin{cfa} 1276 `*` int x; 1277 int y; 1278 \end{cfa} 1279 & 1280 \begin{cfa} 1281 int `*`x, y; 1282 1283 \end{cfa} 1284 \end{tabular} 1285 \lstMakeShortInline@% 1286 \end{quote} 1287 which is prescribing a safety benefit. 1288 Other examples are: 1289 \begin{quote} 1290 \lstDeleteShortInline@% 1291 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1292 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ 1293 \begin{cfa} 1294 [ 5 ] int z; 1295 [ 5 ] * char w; 1296 * [ 5 ] double v; 1297 struct s { 1298 int f0:3; 1299 * int f1; 1300 [ 5 ] * int f2; 1301 }; 1302 \end{cfa} 1303 & 1304 \begin{cfa} 1305 int z[ 5 ]; 1306 char * w[ 5 ]; 1307 double (* v)[ 5 ]; 1308 struct s { 1309 int f0:3; 1310 int * f1; 1311 int * f2[ 5 ] 1312 }; 1313 \end{cfa} 1314 & 1315 \begin{cfa} 1316 // array of 5 integers 1317 // array of 5 pointers to char 1318 // pointer to array of 5 doubles 1319 1320 // common bit field syntax 1321 1322 1323 1324 \end{cfa} 1325 \end{tabular} 1326 \lstMakeShortInline@% 1327 \end{quote} 1328 1329 All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg: 1330 \begin{quote} 1331 \lstDeleteShortInline@% 1332 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 1333 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\ 1334 \begin{cfa} 1335 const * const int x; 1336 const * [ 5 ] const int y; 1337 \end{cfa} 1338 & 1339 \begin{cfa} 1340 int const * const x; 1341 const int (* const y)[ 5 ] 1342 \end{cfa} 1343 & 1344 \begin{cfa} 1345 // const pointer to const integer 1346 // const pointer to array of 5 const integers 1347 \end{cfa} 1348 \end{tabular} 1349 \lstMakeShortInline@% 1350 \end{quote} 1351 All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier} 1352 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg: 1353 \begin{quote} 1354 \lstDeleteShortInline@% 1355 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1356 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ 1357 \begin{cfa} 1358 extern [ 5 ] int x; 1359 static * const int y; 1360 \end{cfa} 1361 & 1362 \begin{cfa} 1363 int extern x[ 5 ]; 1364 const int static * y; 1365 \end{cfa} 1366 & 1367 \begin{cfa} 1368 // externally visible array of 5 integers 1369 // internally visible pointer to constant int 1370 \end{cfa} 1371 \end{tabular} 1372 \lstMakeShortInline@% 1373 \end{quote} 1374 1375 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©: 1376 \begin{quote} 1377 \lstDeleteShortInline@% 1378 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1379 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1380 \begin{cfa} 1381 y = (`* int`)x; 1382 i = sizeof(`[ 5 ] * int`); 1383 \end{cfa} 1384 & 1385 \begin{cfa} 1386 y = (`int *`)x; 1387 i = sizeof(`int * [ 5 ]`); 1388 \end{cfa} 1389 \end{tabular} 1390 \lstMakeShortInline@% 1391 \end{quote} 1392 1393 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration. 1394 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style. 1395 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems. 1191 1396 1192 1397 -
src/libcfa/bits/debug.c
reb7f20c r41fcd94 11 11 // Last Modified By : 12 12 // Last Modified On : 13 // Update Count : 013 // Update Count : 1 14 14 // 15 15 … … 47 47 void __cfaabi_dbg_bits_release() __attribute__((__weak__)) {} 48 48 49 void __cfaabi_dbg_bits_print_safe ( const char fmt[], ... ) __attribute__(( format 49 void __cfaabi_dbg_bits_print_safe ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) { 50 50 va_list args; 51 51 … … 60 60 } 61 61 62 void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format 62 void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) { 63 63 va_list args; 64 64 … … 76 76 } 77 77 78 void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format 78 void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )) { 79 79 va_list args; 80 80 -
src/libcfa/bits/debug.h
reb7f20c r41fcd94 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 10:02:24 201713 // Update Count : 112 // Last Modified On : Thu Feb 8 12:35:19 2018 13 // Update Count : 2 14 14 // 15 15 … … 41 41 extern void __cfaabi_dbg_bits_acquire(); 42 42 extern void __cfaabi_dbg_bits_release(); 43 extern void __cfaabi_dbg_bits_print_safe ( const char fmt[], ... ) __attribute__(( format 44 extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format 43 extern void __cfaabi_dbg_bits_print_safe ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )); 44 extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )); 45 45 extern void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list arg ); 46 extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format 46 extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )); 47 47 #ifdef __cforall 48 48 } -
src/libcfa/bits/defs.h
reb7f20c r41fcd94 10 10 // Created On : Thu Nov 9 13:24:10 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Jan 2 09:17:06201813 // Update Count : 212 // Last Modified On : Thu Feb 8 16:22:41 2018 13 // Update Count : 8 14 14 // 15 15 … … 34 34 35 35 #ifdef __cforall 36 #ifndef __NO_ABORT_OVERLOAD 37 void abort ( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)); 38 #endif 36 void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 39 37 extern "C" { 40 38 #endif 41 void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));39 void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 42 40 #ifdef __cforall 43 41 } -
src/libcfa/concurrency/coroutine.c
reb7f20c r41fcd94 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 21 22:34:57 201713 // Update Count : 112 // Last Modified On : Thu Feb 8 16:10:31 2018 13 // Update Count : 4 14 14 // 15 15 … … 77 77 __cfaabi_dbg_debug_do( 78 78 if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) { 79 abort f( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );79 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) ); 80 80 } 81 81 ); … … 135 135 __cfaabi_dbg_debug_do( 136 136 if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) { 137 abort f( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );137 abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) ); 138 138 } // if 139 139 ); 140 140 141 141 if ( (intptr_t)storage == 0 ) { 142 abort f( "Attempt to allocate %d bytes of storage for coroutine or task execution-state but insufficient memory available.", size );142 abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size ); 143 143 } // if 144 144 -
src/libcfa/concurrency/invoke.c
reb7f20c r41fcd94 10 10 // Created On : Tue Jan 17 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Feb 6 23:00:57201813 // Update Count : 312 // Last Modified On : Thu Feb 8 16:18:11 2018 13 // Update Count : 4 14 14 // 15 15 … … 51 51 //Final suspend, should never return 52 52 __leave_coroutine(); 53 abortf( "Resumed dead coroutine" );53 __cabi_abort( "Resumed dead coroutine" ); 54 54 } 55 55 … … 81 81 //Final suspend, should never return 82 82 __leave_thread_monitor( thrd ); 83 abortf( "Resumed dead thread" );83 __cabi_abort( "Resumed dead thread" ); 84 84 } 85 85 -
src/libcfa/concurrency/monitor.c
reb7f20c r41fcd94 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jul 31 14:59:05 201713 // Update Count : 312 // Last Modified On : Thu Feb 8 16:12:20 2018 13 // Update Count : 4 14 14 // 15 15 … … 87 87 thread_desc * thrd = this_thread; 88 88 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 90 90 91 91 if( !this->owner ) { … … 93 93 set_owner( this, thrd ); 94 94 95 __cfaabi_dbg_print_safe( "Kernel : mon is free \n");95 __cfaabi_dbg_print_safe( "Kernel : mon is free \n" ); 96 96 } 97 97 else if( this->owner == thrd) { … … 99 99 this->recursion += 1; 100 100 101 __cfaabi_dbg_print_safe( "Kernel : mon already owned \n");101 __cfaabi_dbg_print_safe( "Kernel : mon already owned \n" ); 102 102 } 103 103 else if( is_accepted( this, group) ) { … … 108 108 reset_mask( this ); 109 109 110 __cfaabi_dbg_print_safe( "Kernel : mon accepts \n");110 __cfaabi_dbg_print_safe( "Kernel : mon accepts \n" ); 111 111 } 112 112 else { 113 __cfaabi_dbg_print_safe( "Kernel : blocking \n");113 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 114 114 115 115 // Some one else has the monitor, wait in line for it … … 118 118 BlockInternal( &this->lock ); 119 119 120 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this);120 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 121 121 122 122 // BlockInternal will unlock spinlock, no need to unlock ourselves … … 124 124 } 125 125 126 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this);126 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 127 127 128 128 // Release the lock and leave … … 136 136 thread_desc * thrd = this_thread; 137 137 138 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);138 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); 139 139 140 140 141 141 if( !this->owner ) { 142 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);142 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 143 143 144 144 // No one has the monitor, just take it … … 151 151 // We already have the monitor... but where about to destroy it so the nesting will fail 152 152 // Abort! 153 abort f("Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.");153 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex." ); 154 154 } 155 155 … … 158 158 __monitor_group_t group = { &this, 1, func }; 159 159 if( is_accepted( this, group) ) { 160 __cfaabi_dbg_print_safe( "Kernel : mon accepts dtor, block and signal it \n");160 __cfaabi_dbg_print_safe( "Kernel : mon accepts dtor, block and signal it \n" ); 161 161 162 162 // Wake the thread that is waiting for this … … 177 177 } 178 178 else { 179 __cfaabi_dbg_print_safe( "Kernel : blocking \n");179 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 180 180 181 181 wait_ctx( this_thread, 0 ) … … 190 190 } 191 191 192 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);192 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this); 193 193 194 194 } … … 199 199 lock( this->lock __cfaabi_dbg_ctx2 ); 200 200 201 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner);201 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner); 202 202 203 203 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", this_thread, this->owner, this->recursion, this ); … … 209 209 // it means we don't need to do anything 210 210 if( this->recursion != 0) { 211 __cfaabi_dbg_print_safe( "Kernel : recursion still %d\n", this->recursion);211 __cfaabi_dbg_print_safe( "Kernel : recursion still %d\n", this->recursion); 212 212 unlock( this->lock ); 213 213 return; … … 228 228 __cfaabi_dbg_debug_do( 229 229 if( this_thread != this->owner ) { 230 abort f("Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);230 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner); 231 231 } 232 232 if( this->recursion != 1 ) { 233 abort f("Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);233 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 234 234 } 235 235 ) … … 256 256 // If we haven't left the last level of recursion 257 257 // it must mean there is an error 258 if( this->recursion != 0) { abort f("Thread internal monitor has unbalanced recursion"); }258 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); } 259 259 260 260 // Fetch the next thread, can be null … … 302 302 (this_thread->monitors){m, count, func}; 303 303 304 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count);304 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count); 305 305 306 306 // Enter the monitors in order … … 308 308 enter( group ); 309 309 310 // __cfaabi_dbg_print_safe( "MGUARD : entered\n");310 // __cfaabi_dbg_print_safe( "MGUARD : entered\n" ); 311 311 } 312 312 … … 314 314 // Dtor for monitor guard 315 315 void ^?{}( monitor_guard_t & this ) { 316 // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count);316 // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count); 317 317 318 318 // Leave the monitors in order 319 319 leave( this.m, this.count ); 320 320 321 // __cfaabi_dbg_print_safe( "MGUARD : left\n");321 // __cfaabi_dbg_print_safe( "MGUARD : left\n" ); 322 322 323 323 // Restore thread context … … 427 427 thread_desc * this_thrd = this_thread; 428 428 if ( this.monitor_count != this_thrd->monitors.size ) { 429 abort f( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );429 abort( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size ); 430 430 } 431 431 432 432 for(int i = 0; i < this.monitor_count; i++) { 433 433 if ( this.monitors[i] != this_thrd->monitors[i] ) { 434 abort f( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );434 abort( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] ); 435 435 } 436 436 } … … 534 534 if(actual_count == 0) return; 535 535 536 __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n" );536 __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n" ); 537 537 538 538 // Create storage for monitor context … … 551 551 __acceptable_t& accepted = mask[index]; 552 552 if( accepted.is_dtor ) { 553 __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n" );553 __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n" ); 554 554 verifyf( accepted.size == 1, "ERROR: Accepted dtor has more than 1 mutex parameter." ); 555 555 … … 563 563 } 564 564 else { 565 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n" );565 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n" ); 566 566 567 567 // Create the node specific to this wait operation … … 577 577 } 578 578 #endif 579 __cfaabi_dbg_print_buffer_local( "\n" );579 __cfaabi_dbg_print_buffer_local( "\n" ); 580 580 581 581 // Set the owners to be the next thread … … 588 588 monitor_restore; 589 589 590 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n" );590 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n" ); 591 591 } 592 592 … … 598 598 599 599 if( duration == 0 ) { 600 __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n" );600 __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n" ); 601 601 602 602 unlock_all( locks, count ); … … 607 607 608 608 609 verifyf( duration < 0, "Timeout on waitfor statments not supported yet." );610 611 __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n" );609 verifyf( duration < 0, "Timeout on waitfor statments not supported yet." ); 610 611 __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n" ); 612 612 613 613 // Create the node specific to this wait operation … … 631 631 monitor_restore; 632 632 633 __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n" );633 __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n" ); 634 634 635 635 __cfaabi_dbg_print_buffer_local( "Kernel : accepted %d\n", *mask.accepted); … … 640 640 641 641 static inline void set_owner( monitor_desc * this, thread_desc * owner ) { 642 // __cfaabi_dbg_print_safe( "Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );642 // __cfaabi_dbg_print_safe( "Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner ); 643 643 644 644 //Pass the monitor appropriately … … 672 672 static inline thread_desc * next_thread( monitor_desc * this ) { 673 673 //Check the signaller stack 674 __cfaabi_dbg_print_safe( "Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top);674 __cfaabi_dbg_print_safe( "Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top); 675 675 __condition_criterion_t * urgent = pop( this->signal_stack ); 676 676 if( urgent ) { … … 814 814 thread_desc * thrd = this_thread; 815 815 if( !this.monitors ) { 816 // __cfaabi_dbg_print_safe( "Branding\n");816 // __cfaabi_dbg_print_safe( "Branding\n" ); 817 817 assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data ); 818 818 this.monitor_count = thrd->monitors.size; -
src/libcfa/concurrency/preemption.c
reb7f20c r41fcd94 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Feb 6 15:00:36201813 // Update Count : 1 012 // Last Modified On : Thu Feb 8 16:12:58 2018 13 // Update Count : 12 14 14 // 15 15 … … 197 197 198 198 if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 199 abort f( "internal error, pthread_sigmask" );199 abort( "internal error, pthread_sigmask" ); 200 200 } 201 201 } … … 208 208 209 209 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) { 210 abort f( "internal error, pthread_sigmask" );210 abort( "internal error, pthread_sigmask" ); 211 211 } 212 212 } … … 247 247 // Called from kernel_startup 248 248 void kernel_start_preemption() { 249 __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n");249 __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" ); 250 250 251 251 // Start with preemption disabled until ready … … 268 268 // Called from kernel_shutdown 269 269 void kernel_stop_preemption() { 270 __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n");270 __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" ); 271 271 272 272 // Block all signals since we are already shutting down … … 284 284 // Preemption is now fully stopped 285 285 286 __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n");286 __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n" ); 287 287 } 288 288 … … 328 328 if( !preemption_ready() ) { return; } 329 329 330 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);330 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread); 331 331 332 332 preemption_in_progress = true; // Sync flag : prevent recursive calls to the signal handler … … 348 348 349 349 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) { 350 abort f( "internal error, pthread_sigmask" );350 abort( "internal error, pthread_sigmask" ); 351 351 } 352 352 … … 365 365 continue; 366 366 case EINVAL : 367 abort f("Timeout was invalid.");367 abort( "Timeout was invalid." ); 368 368 default: 369 abort f("Unhandled error %d", err);369 abort( "Unhandled error %d", err); 370 370 } 371 371 } … … 374 374 assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int); 375 375 376 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );376 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int ); 377 377 // Switch on the code (a.k.a. the sender) to 378 378 switch( info.si_code ) … … 382 382 case SI_TIMER: 383 383 case SI_KERNEL: 384 // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n");384 // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" ); 385 385 lock( event_kernel->lock __cfaabi_dbg_ctx2 ); 386 386 tick_preemption(); … … 396 396 397 397 EXIT: 398 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n");398 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" ); 399 399 return NULL; 400 400 } -
src/libcfa/interpose.c
reb7f20c r41fcd94 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 7 09:05:18201813 // Update Count : 5912 // Last Modified On : Thu Feb 8 16:18:09 2018 13 // Update Count : 75 14 14 // 15 15 … … 28 28 } 29 29 30 #define __NO_ABORT_OVERLOAD // no abort overload avoid ambiguities31 30 #include "bits/debug.h" 32 31 #include "bits/defs.h" … … 51 50 error = dlerror(); 52 51 if ( error ) { 53 abort f( "interpose_symbol : failed to open libc, %s\n", error );52 abort( "interpose_symbol : failed to open libc, %s\n", error ); 54 53 } 55 54 #endif … … 69 68 70 69 error = dlerror(); 71 if ( error ) abort f( "interpose_symbol : internal error, %s\n", error );70 if ( error ) abort( "interpose_symbol : internal error, %s\n", error ); 72 71 73 72 return originalFunc.fptr; … … 98 97 99 98 struct { 100 __typeof__( exit ) exit __attribute__(( noreturn));101 __typeof__( abort ) abort __attribute__(( noreturn));99 void (* exit)( int ) __attribute__ (( __noreturn__ )); 100 void (* abort)( void ) __attribute__ (( __noreturn__ )); 102 101 } __cabi_libc; 103 102 … … 123 122 124 123 // Forward declare abort after the __typeof__ call to avoid ambiguities 125 void abort ( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)); 124 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 125 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 126 126 127 127 extern "C" { 128 void abort( void ) __attribute__ (( __nothrow__, __leaf__, __noreturn__)) {129 abort f( NULL );130 } 131 132 void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {128 void abort( void ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) { 129 abort( NULL ); 130 } 131 132 void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) { 133 133 va_list argp; 134 134 va_start( argp, fmt ); … … 137 137 } 138 138 139 void exit( int __status ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {140 __cabi_libc.exit( __status);141 } 142 } 143 144 void * kernel_abort ( void ) __attribute__ (( __nothrow__, __leaf__, __weak__)) { return NULL; }145 void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ (( __nothrow__, __leaf__, __weak__)) {}146 int kernel_abort_lastframe( void ) __attribute__ (( __nothrow__, __leaf__, __weak__)) { return 4; }139 void exit( int status ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) { 140 __cabi_libc.exit( status ); 141 } 142 } 143 144 void * kernel_abort ( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return NULL; } 145 void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) {} 146 int kernel_abort_lastframe( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return 4; } 147 147 148 148 enum { abort_text_size = 1024 }; … … 150 150 static int abort_lastframe; 151 151 152 void abort( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) { 152 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) { 153 va_list args; 154 va_start( args, fmt ); 155 vfprintf( stderr, fmt, args ); 156 va_end( args ); 157 __cabi_libc.exit( status ); 158 } 159 160 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) { 153 161 void * kernel_data = kernel_abort(); // must be done here to lock down kernel 154 162 int len; … … 226 234 227 235 void sigHandler_segv( __CFA_SIGPARMS__ ) { 228 abort f( "Addressing invalid memory at location %p\n"236 abort( "Addressing invalid memory at location %p\n" 229 237 "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n", 230 238 sfp->si_addr ); … … 232 240 233 241 void sigHandler_ill( __CFA_SIGPARMS__ ) { 234 abort f( "Executing illegal instruction at location %p.\n"242 abort( "Executing illegal instruction at location %p.\n" 235 243 "Possible cause is stack corruption.\n", 236 244 sfp->si_addr ); … … 248 256 default: msg = "unknown"; 249 257 } // choose 250 abort f( "Computation error %s at location %p.\n", msg, sfp->si_addr );258 abort( "Computation error %s at location %p.\n", msg, sfp->si_addr ); 251 259 } 252 260 -
src/prelude/builtins.c
reb7f20c r41fcd94 9 9 // Author : Peter A. Buhr 10 10 // Created On : Fri Jul 21 16:21:03 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : T us Jul 25 15:33:00 201713 // Update Count : 1 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 8 12:47:59 2018 13 // Update Count : 19 14 14 // 15 15 … … 20 20 #include "../libcfa/virtual.h" 21 21 #include "../libcfa/exception.h" 22 23 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 24 void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 22 25 23 26 // exponentiation operator implementation
Note: See TracChangeset
for help on using the changeset viewer.