[26ca815] | 1 | \chapter{Implementation} |
---|
| 2 | % Goes over how all the features are implemented. |
---|
| 3 | |
---|
| 4 | \section{Virtual System} |
---|
| 5 | % Virtual table rules. Virtual tables, the pointer to them and the cast. |
---|
| 6 | The \CFA virtual system only has one public facing feature: virtual casts. |
---|
| 7 | However there is a lot of structure to support that and provide some other |
---|
| 8 | features for the standard library. |
---|
| 9 | |
---|
| 10 | All of this is accessed through a field inserted at the beginning of every |
---|
| 11 | virtual type. Currently it is called \codeC{virtual_table} but it is not |
---|
| 12 | ment to be accessed by the user. This field is a pointer to the type's |
---|
| 13 | virtual table instance. It is assigned once during the object's construction |
---|
| 14 | and left alone after that. |
---|
| 15 | |
---|
| 16 | \subsection{Virtual Table Construction} |
---|
| 17 | For each virtual type a virtual table is constructed. This is both a new type |
---|
| 18 | and an instance of that type. Other instances of the type could be created |
---|
| 19 | but the system doesn't use them. So this section will go over the creation of |
---|
| 20 | the type and the instance. |
---|
| 21 | |
---|
| 22 | Creating the single instance is actually very important. The address of the |
---|
| 23 | table acts as the unique identifier for the virtual type. Similarly the first |
---|
| 24 | field in every virtual table is the parent's id; a pointer to the parent |
---|
| 25 | virtual table instance. |
---|
| 26 | |
---|
| 27 | The remaining fields contain the type's virtual members. First come the ones |
---|
| 28 | present on the parent type, in the same order as they were the parent, and |
---|
| 29 | then any that this type introduces. The types of the ones inherited from the |
---|
| 30 | parent may have a slightly modified type, in that references to the |
---|
| 31 | dispatched type are replaced with the current virtual type. These are always |
---|
| 32 | taken by pointer or reference. |
---|
| 33 | |
---|
| 34 | The structure itself is created where the virtual type is created. The name |
---|
| 35 | of the type is created by mangling the name of the base type. The name of the |
---|
| 36 | instance is also generated by name mangling. |
---|
| 37 | |
---|
| 38 | The fields are initialized automatically. |
---|
| 39 | The parent field is initialized by getting the type of the parent field and |
---|
| 40 | using that to calculate the mangled name of the parent's virtual table type. |
---|
| 41 | There are two special fields that are included like normal fields but have |
---|
| 42 | special initialization rules: the \codeC{size} field is the type's size and is |
---|
| 43 | initialized with a sizeof expression, the \codeC{align} field is the type's |
---|
| 44 | alignment and uses an alignof expression. The remaining fields are resolved |
---|
| 45 | to a name matching the field's name and type using the normal visibility |
---|
| 46 | and overload resolution rules of the type system. |
---|
| 47 | |
---|
| 48 | These operations are split up into several groups depending on where they |
---|
| 49 | take place which can vary for monomorphic and polymorphic types. The first |
---|
| 50 | devision is between the declarations and the definitions. Declarations, such |
---|
| 51 | as a function signature or a structure's name, must always be visible but may |
---|
| 52 | be repeated so they go in headers. Definitions, such as function bodies and a |
---|
| 53 | structure's layout, don't have to be visible on use but must occur exactly |
---|
| 54 | once and go into source files. |
---|
| 55 | |
---|
| 56 | The declarations include the virtual type definition and forward declarations |
---|
| 57 | of the virtual table instance, constructor, message function and |
---|
| 58 | \codeCFA{get_exception_vtable}. The definition includes the storage and |
---|
| 59 | initialization of the virtual table instance and the bodies of the three |
---|
| 60 | functions. |
---|
| 61 | |
---|
| 62 | Monomorphic instances put all of these two groups in one place each. |
---|
| 63 | |
---|
| 64 | Polymorphic instances also split out the core declarations and definitions |
---|
| 65 | from the per-instance information. The virtual table type and most of the |
---|
| 66 | functions are polymorphic so they are all part of the core. The virtual table |
---|
| 67 | instance and the \codeCFA{get_exception_vtable} function. |
---|
| 68 | |
---|
| 69 | Coroutines and threads need instances of \codeCFA{CoroutineCancelled} and |
---|
| 70 | \codeCFA{ThreadCancelled} respectively to use all of their functionality. |
---|
| 71 | When a new data type is declared with \codeCFA{coroutine} or \codeCFA{thread} |
---|
| 72 | the forward declaration for the instance is created as well. The definition |
---|
| 73 | of the virtual table is created at the definition of the main function. |
---|
| 74 | |
---|
| 75 | \subsection{Virtual Cast} |
---|
| 76 | Virtual casts are implemented as a function call that does the check and a |
---|
| 77 | old C-style cast to do the type conversion. The C-cast is just to make sure |
---|
| 78 | the generated code is correct so the rest of the section is about that |
---|
| 79 | function. |
---|
| 80 | |
---|
| 81 | The function is \codeC{__cfa__virtual_cast} and it is implemented in the |
---|
| 82 | standard library. It takes a pointer to the target type's virtual table and |
---|
| 83 | the object pointer being cast. The function is very simple, getting the |
---|
| 84 | object's virtual table pointer and then checking to see if it or any of |
---|
| 85 | its ancestors, by using the parent pointers, are the same as the target type |
---|
| 86 | virtual table pointer. It does this in a simple loop. |
---|
| 87 | |
---|
| 88 | For the generated code a forward decaration of the virtual works as follows. |
---|
| 89 | There is a forward declaration of \codeC{__cfa__virtual_cast} in every cfa |
---|
| 90 | file so it can just be used. The object argument is the expression being cast |
---|
| 91 | so that is just placed in the argument list. |
---|
| 92 | |
---|
| 93 | To build the target type parameter the compiler will create a mapping from |
---|
| 94 | concrete type-name -- so for polymorphic types the parameters are filled in |
---|
| 95 | -- to virtual table address. Every virtual table declaraction is added to the |
---|
| 96 | this table; repeats are ignored unless they have conflicting definitions. |
---|
| 97 | This does mean the declaractions have to be in scope, but they should usually |
---|
| 98 | be introduced as part of the type definition. |
---|
| 99 | |
---|
| 100 | \section{Exceptions} |
---|
| 101 | % Anything about exception construction. |
---|
| 102 | |
---|
| 103 | \section{Unwinding} |
---|
| 104 | % Adapt the unwind chapter, just describe the sections of libunwind used. |
---|
| 105 | % Mention that termination and cancellation use it. Maybe go into why |
---|
| 106 | % resumption doesn't as well. |
---|
| 107 | |
---|
| 108 | Many modern languages work with an interal stack that function push and pop |
---|
| 109 | their local data to. Stack unwinding removes large sections of the stack, |
---|
| 110 | often across functions. |
---|
| 111 | |
---|
| 112 | At a very basic level this can be done with \codeC{setjmp} \& \codeC{longjmp} |
---|
| 113 | which simply move the top of the stack, discarding everything on the stack |
---|
| 114 | above a certain point. However this ignores all the clean-up code that should |
---|
| 115 | be run when certain sections of the stack are removed (for \CFA these are from |
---|
| 116 | destructors and finally clauses) and also requires that the point to which the |
---|
| 117 | stack is being unwound is known ahead of time. libunwind is used to address |
---|
| 118 | both of these problems. |
---|
| 119 | |
---|
| 120 | Libunwind, provided in \texttt{unwind.h} on most platorms, is a C library |
---|
| 121 | that provides \CPP style stack unwinding. Its operation is divided into two |
---|
| 122 | phases. The search phase -- phase 1 -- is used to scan the stack and decide |
---|
| 123 | where the unwinding will stop, this allows for a dynamic target. The clean-up |
---|
| 124 | phase -- phase 2 -- does the actual unwinding and also runs any clean-up code |
---|
| 125 | as it goes. |
---|
| 126 | |
---|
| 127 | To use the libunwind each function must have a personality function and an |
---|
| 128 | LSDA (Language Specific Data Area). Libunwind actually does very little, it |
---|
| 129 | simply moves down the stack from function to function. Most of the actions are |
---|
| 130 | implemented by the personality function which libunwind calls on every |
---|
| 131 | function. Since this is shared across many functions or even every function in |
---|
| 132 | a language it will need a bit more information. This is provided by the LSDA |
---|
| 133 | which has the unique information for each function. |
---|
| 134 | |
---|
| 135 | Theoretically the LSDA can contain anything but conventionally it is a table |
---|
| 136 | with entries reperenting areas of the function and what has to be done there |
---|
| 137 | during unwinding. These areas are described in terms of where the instruction |
---|
| 138 | pointer is. If the current value of the instruction pointer is between two |
---|
| 139 | values reperenting the beginning and end of a region then execution is |
---|
| 140 | currently being executed. These are used to mark out try blocks and the |
---|
| 141 | scopes of objects with destructors to run. |
---|
| 142 | |
---|
| 143 | GCC will generate an LSDA and attach its personality function with the |
---|
| 144 | \texttt{-fexceptions} flag. However this only handles the cleanup attribute. |
---|
| 145 | This attribute is used on a variable and specifies a function that should be |
---|
| 146 | run when the variable goes out of scope. The function is passed a pointer to |
---|
| 147 | the object as well so it can be used to mimic destructors. It however cannot |
---|
| 148 | be used to mimic try statements. |
---|
| 149 | |
---|
| 150 | \subsection{Implementing Personality Functions} |
---|
| 151 | Personality functions have a complex interface specified by libunwind. |
---|
| 152 | This section will cover some of the important parts of that interface. |
---|
| 153 | |
---|
| 154 | \begin{lstlisting} |
---|
| 155 | typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( |
---|
| 156 | int version, |
---|
| 157 | _Unwind_Action action, |
---|
| 158 | _Unwind_Exception_Class exception_class, |
---|
| 159 | _Unwind_Exception * exception, |
---|
| 160 | struct _Unwind_Context * context); |
---|
| 161 | \end{lstlisting} |
---|
| 162 | |
---|
| 163 | The return value, the reason code, is an enumeration of possible messages |
---|
| 164 | that can be passed several places in libunwind. It includes a number of |
---|
| 165 | messages for special cases (some of which should never be used by the |
---|
| 166 | personality function) and error codes but unless otherwise noted the |
---|
| 167 | personality function should always return \codeC{_URC_CONTINUE_UNWIND}. |
---|
| 168 | |
---|
| 169 | The \codeC{version} argument is the verson of the implementation that is |
---|
| 170 | calling the personality function. At this point it appears to always be 1 and |
---|
| 171 | it will likely stay that way until a new version of the API is updated. |
---|
| 172 | |
---|
| 173 | The \codeC{action} argument is set of flags that tell the personality |
---|
| 174 | function when it is being called and what it must do on this invocation. |
---|
| 175 | The flags are as follows: |
---|
| 176 | \begin{itemize} |
---|
| 177 | \item\codeC{_UA_SEARCH_PHASE}: This flag is set whenever the personality |
---|
| 178 | function is called during the search phase. The personality function should |
---|
| 179 | decide if unwinding will stop in this function or not. If it does then the |
---|
| 180 | personality function should return \codeC{_URC_HANDLER_FOUND}. |
---|
| 181 | \item\codeC{_UA_CLEANUP_PHASE}: This flag is set whenever the personality |
---|
| 182 | function is called during the cleanup phase. If no other flags are set this |
---|
| 183 | means the entire frame will be unwound and all cleanup code should be run. |
---|
| 184 | \item\codeC{_UA_HANDLER_FRAME}: This flag is set during the cleanup phase |
---|
| 185 | on the function frame that found the handler. The personality function must |
---|
| 186 | prepare to return to normal code execution and return |
---|
| 187 | \codeC{_URC_INSTALL_CONTEXT}. |
---|
| 188 | \item\codeC{_UA_FORCE_UNWIND}: This flag is set if the personality function |
---|
| 189 | is called through a forced unwind call. Forced unwind only performs the |
---|
| 190 | cleanup phase and uses a different means to decide when to stop. See its |
---|
| 191 | section below. |
---|
| 192 | \end{itemize} |
---|
| 193 | |
---|
| 194 | The \codeC{exception_class} argument is a copy of the \codeC{exception}'s |
---|
| 195 | \codeC{exception_class} field. |
---|
| 196 | |
---|
| 197 | The \codeC{exception} argument is a pointer to the user provided storage |
---|
| 198 | object. It has two public fields, the exception class which is actually just |
---|
| 199 | a number that identifies the exception handling mechanism that created it and |
---|
| 200 | the other is the clean-up function. The clean-up function is called if the |
---|
| 201 | exception needs to |
---|
| 202 | |
---|
| 203 | The \codeC{context} argument is a pointer to an opaque type. This is passed |
---|
| 204 | to the many helper functions that can be called inside the personality |
---|
| 205 | function. |
---|
| 206 | |
---|
| 207 | \subsection{Raise Exception} |
---|
| 208 | This could be considered the central function of libunwind. It preforms the |
---|
| 209 | two staged unwinding the library is built around and most of the rest of the |
---|
| 210 | interface of libunwind is here to support it. It's signature is as follows: |
---|
| 211 | |
---|
| 212 | \begin{lstlisting} |
---|
| 213 | _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *); |
---|
| 214 | \end{lstlisting} |
---|
| 215 | |
---|
| 216 | When called the function begins the search phase, calling the personality |
---|
| 217 | function of the most recent stack frame. It will continue to call personality |
---|
| 218 | functions traversing the stack new-to-old until a function finds a handler or |
---|
| 219 | the end of the stack is reached. In the latter case raise exception will |
---|
| 220 | return with \codeC{_URC_END_OF_STACK}. |
---|
| 221 | |
---|
| 222 | Once a handler has been found raise exception continues onto the the cleanup |
---|
| 223 | phase. Once again it will call the personality functins of each stack frame |
---|
| 224 | from newest to oldest. This pass will stop at the stack frame that found the |
---|
| 225 | handler last time, if that personality function does not install the handler |
---|
| 226 | it is an error. |
---|
| 227 | |
---|
| 228 | If an error is encountered raise exception will return either |
---|
| 229 | \codeC{_URC_FATAL_PHASE1_ERROR} or \codeC{_URC_FATAL_PHASE2_ERROR} depending |
---|
| 230 | on when the error occured. |
---|
| 231 | |
---|
| 232 | \subsection{Forced Unwind} |
---|
| 233 | This is the second big function in libunwind. It also unwinds a stack but it |
---|
| 234 | does not use the search phase. Instead another function, the stop function, |
---|
| 235 | is used to decide when to stop. |
---|
| 236 | |
---|
| 237 | \begin{lstlisting} |
---|
| 238 | _Unwind_Reason_Code _Unwind_ForcedUnwind( |
---|
| 239 | _Unwind_Exception *, _Unwind_Stop_Fn, void *); |
---|
| 240 | \end{lstlisting} |
---|
| 241 | |
---|
| 242 | The exception is the same as the one passed to raise exception. The extra |
---|
| 243 | arguments are the stop function and the stop parameter. The stop function has |
---|
| 244 | a similar interface as a personality function, except it is also passed the |
---|
| 245 | stop parameter. |
---|
| 246 | |
---|
| 247 | \begin{lstlisting} |
---|
| 248 | typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)( |
---|
| 249 | int version, |
---|
| 250 | _Unwind_Action action, |
---|
| 251 | _Unwind_Exception_Class exception_class, |
---|
| 252 | _Unwind_Exception * exception, |
---|
| 253 | struct _Unwind_Context * context, |
---|
| 254 | void * stop_parameter); |
---|
| 255 | \end{lstlisting} |
---|
| 256 | |
---|
| 257 | The stop function is called at every stack frame before the personality |
---|
| 258 | function is called and then once more once after all frames of the stack have |
---|
| 259 | been unwound. |
---|
| 260 | |
---|
| 261 | Each time it is called the stop function should return \codeC{_URC_NO_REASON} |
---|
| 262 | or transfer control directly to other code outside of libunwind. The |
---|
| 263 | framework does not provide any assistance here. |
---|
| 264 | |
---|
| 265 | Its arguments are the same as the paired personality function. |
---|
| 266 | The actions \codeC{_UA_CLEANUP_PHASE} and \codeC{_UA_FORCE_UNWIND} are always |
---|
| 267 | set when it is called. By the official standard that is all but both GCC and |
---|
| 268 | Clang add an extra action on the last call at the end of the stack: |
---|
| 269 | \codeC{_UA_END_OF_STACK}. |
---|
| 270 | |
---|
| 271 | \section{Exception Context} |
---|
| 272 | % Should I have another independent section? |
---|
| 273 | % There are only two things in it, top_resume and current_exception. How it is |
---|
| 274 | % stored changes depending on wheither or not the thread-library is linked. |
---|
| 275 | |
---|
| 276 | The exception context is a piece of global storage used to maintain data |
---|
| 277 | across different exception operations and to communicate between different |
---|
| 278 | components. |
---|
| 279 | |
---|
| 280 | Each stack has its own exception context. In a purely sequental program, using |
---|
| 281 | only core Cforall, there is only one stack and the context is global. However |
---|
| 282 | if the library \texttt{libcfathread} is linked then there can be multiple |
---|
| 283 | stacks so they will each need their own. |
---|
| 284 | |
---|
| 285 | To handle this code always gets the exception context from the function |
---|
| 286 | \codeC{this_exception_context}. The main exception handling code is in |
---|
| 287 | \texttt{libcfa} and that library also defines the function as a weak symbol |
---|
| 288 | so it acts as a default. Meanwhile in \texttt{libcfathread} the function is |
---|
| 289 | defined as a strong symbol that replaces it when the libraries are linked |
---|
| 290 | together. |
---|
| 291 | |
---|
| 292 | The version of the function defined in \texttt{libcfa} is very simple. It |
---|
| 293 | returns a pointer to a global static variable. With only one stack this |
---|
| 294 | global instance is associated with the only stack. |
---|
| 295 | |
---|
| 296 | The version of the function defined in \texttt{libcfathread} has to handle |
---|
| 297 | more as there are multiple stacks. The exception context is included as |
---|
| 298 | part of the per-stack data stored as part of coroutines. In the cold data |
---|
| 299 | section, stored at the base of each stack, is the exception context for that |
---|
| 300 | stack. The \codeC{this_exception_context} uses the concurrency library to get |
---|
| 301 | the current coroutine and through it the cold data section and the exception |
---|
| 302 | context. |
---|
| 303 | |
---|
| 304 | \section{Termination} |
---|
| 305 | % Memory management & extra information, the custom function used to implement |
---|
| 306 | % catches. Talk about GCC nested functions. |
---|
| 307 | |
---|
| 308 | Termination exceptions use libunwind quite heavily because it matches the |
---|
| 309 | intended use from \CPP exceptions very closely. The main complication is that |
---|
| 310 | since the \CFA compiler works by translating to C code it cannot generate the |
---|
| 311 | assembly to form the LSDA for try blocks or destructors. |
---|
| 312 | |
---|
| 313 | \subsection{Memory Management} |
---|
| 314 | The first step of termination is to copy the exception into memory managed by |
---|
| 315 | the exception system. Currently the system just uses malloc, without reserved |
---|
| 316 | memory or and ``small allocation" optimizations. The exception handling |
---|
| 317 | mechanism manages memory for the exception as well as memory for libunwind |
---|
| 318 | and the system's own per-exception storage. |
---|
| 319 | |
---|
| 320 | Exceptions are stored in variable sized block. The first component is a fixed |
---|
| 321 | sized data structure that contains the information for libunwind and the |
---|
| 322 | exception system. The second component is a blob of memory that is big enough |
---|
| 323 | to store the exception. Macros with pointer arthritic and type cast are |
---|
| 324 | used to move between the components or go from the embedded |
---|
| 325 | \codeC{_Unwind_Exception} to the entire node. |
---|
| 326 | |
---|
| 327 | All of these nodes are strung together in a linked list. One linked list per |
---|
| 328 | stack, with the head stored in the exception context. Within each linked list |
---|
| 329 | the most recently thrown exception is at the head and the older exceptions |
---|
| 330 | are further down the list. This list format allows exceptions to be thrown |
---|
| 331 | while a different exception is being handled. Only the exception at the head |
---|
| 332 | of the list is currently being handled, the other will wait for the |
---|
| 333 | exceptions before them to be removed. |
---|
| 334 | |
---|
| 335 | The virtual members in the exception's virtual table. The size of the |
---|
| 336 | exception, the copy function and the free function are all in the virtual |
---|
| 337 | table so they are decided per-exception type. The size and copy function are |
---|
| 338 | used right away when the exception is copied in to managed memory. After the |
---|
| 339 | exception is handled the free function is used to clean up the exception and |
---|
| 340 | then the entire node is passed to free. |
---|
| 341 | |
---|
| 342 | \subsection{Try Statements \& Catch Clauses} |
---|
| 343 | The try statements with termination handlers have a pretty complex conversion |
---|
| 344 | to compensate for the lack of assembly generation. Libunwind requires an LSDA |
---|
| 345 | (Language Specific Data Area) and personality function for a function to |
---|
| 346 | unwind across it. The LSDA in particular is hard to generate at the level of |
---|
| 347 | C which is what the \CFA compiler outputs so a work-around is used. |
---|
| 348 | |
---|
| 349 | This work around is a function called \codeC{__cfaehm_try_terminate} in the |
---|
| 350 | standard library. The contents of a try block and the termination handlers |
---|
| 351 | are converted into functions. These are then passed to the try terminate |
---|
| 352 | function and it calls them. This puts the try statements in their own |
---|
| 353 | functions so that no function has to deal with both termination handlers and |
---|
| 354 | destructors. |
---|
| 355 | |
---|
| 356 | This function has some custom embedded assembly that defines its personality |
---|
| 357 | function and LSDA. This is hand coded in C which is why there is only one |
---|
| 358 | version of it, the compiler has no capability to generate it. The personality |
---|
| 359 | function is structured so that it may be expanded, but really it only handles |
---|
| 360 | this one function. Notably it does not handle any destructors so the function |
---|
| 361 | is constructed so that it does need to run it. |
---|
| 362 | |
---|
| 363 | The three functions passed to try terminate are: |
---|
| 364 | \begin{itemize} |
---|
| 365 | \item The try function: This function is the try block, all the code inside |
---|
| 366 | the try block is placed inside the try function. It takes no parameters and |
---|
| 367 | has no return value. This function is called during regular execution to run |
---|
| 368 | the try block. |
---|
| 369 | \item The match function: This function decides if this try statement should |
---|
| 370 | handle any given termination exception. It takes a pointer to the exception |
---|
| 371 | and returns 0 if the exception is not handled here. Otherwise the return value |
---|
| 372 | is the id of the handler that should handle the exception. It is called |
---|
| 373 | during the search phase. |
---|
| 374 | It is constructed from the conditional part of each handler. It runs each |
---|
| 375 | check in turn, first checking to see if the object |
---|
| 376 | \item The catch function: This function handles the exception. It takes a |
---|
| 377 | pointer to the exception and the handler's id and returns nothing. It is |
---|
| 378 | called after the clean-up phase. |
---|
| 379 | It is constructed by stitching together the bodies of each handler |
---|
| 380 | \end{itemize} |
---|
| 381 | All three are created with GCC nested functions. GCC nested functions can be |
---|
| 382 | used to create closures, functions that can refer to the state of other |
---|
| 383 | functions on the stack. This allows the functions to refer to the main |
---|
| 384 | function and all the variables in scope. |
---|
| 385 | |
---|
| 386 | These nested functions and all other functions besides |
---|
| 387 | \codeC{__cfaehm_try_terminate} in \CFA use the GCC personality function and |
---|
| 388 | the \texttt{-fexceptions} flag to generate the LSDA. This allows destructors |
---|
| 389 | to be implemented with the cleanup attribute. |
---|
| 390 | |
---|
| 391 | \section{Resumption} |
---|
| 392 | % The stack-local data, the linked list of nodes. |
---|
| 393 | |
---|
| 394 | Resumption uses a list of nodes for its stack traversal. The head of the list |
---|
| 395 | is stored in the exception context. The nodes in the list just have a pointer |
---|
| 396 | to the next node and a pointer to the handler function. |
---|
| 397 | |
---|
| 398 | The on a resumption throw the this list is traversed. At each node the |
---|
| 399 | handler function is called and is passed the exception by pointer. It returns |
---|
| 400 | true if the exception was handled and false otherwise. |
---|
| 401 | |
---|
| 402 | The handler function does both the matching and catching. It tries each |
---|
| 403 | the condition of \codeCFA{catchResume} in order, top-to-bottom and until it |
---|
| 404 | finds a handler that matches. If no handler matches then the function returns |
---|
| 405 | false. Otherwise the matching handler is run, if it completes successfully |
---|
| 406 | the function returns true. Rethrows, through the \codeCFA{throwResume;} |
---|
| 407 | statement, cause the function to return true. |
---|
| 408 | |
---|
| 409 | \subsection{Libunwind Compatibility} |
---|
| 410 | Resumption does not use libunwind for two simple reasons. The first is that |
---|
| 411 | it does not have to unwind anything so would never need to use the clean-up |
---|
| 412 | phase. Still the search phase could be used to make it free to enter or exit |
---|
| 413 | a try statement with resumption handlers in the same way termination handlers |
---|
| 414 | are for the same trade off in the cost of the throw. This is where the second |
---|
| 415 | reason comes in, there is no way to return from a search without installing |
---|
| 416 | a handler or raising an error. |
---|
| 417 | |
---|
| 418 | Although work arounds could be created none seemed to be worth it for the |
---|
| 419 | prototype. This implementation has no difference in behaviour and is much |
---|
| 420 | simpler. |
---|
| 421 | % Seriously, just compare the size of the two chapters and then consider |
---|
| 422 | % that unwind is required knowledge for that chapter. |
---|
| 423 | |
---|
| 424 | \section{Finally} |
---|
| 425 | % Uses destructors and GCC nested functions. |
---|
| 426 | Finally clauses are a simple decomposition to some of the existing features. |
---|
| 427 | The code in the block is placed into a GCC nested function with a unique name, |
---|
| 428 | no arguments or return values. This nested function is then set as the |
---|
| 429 | clean-up function of an empty object that is declared at the beginning of a |
---|
| 430 | block placed around the contexts of the try statement. |
---|
| 431 | |
---|
| 432 | The rest is handled by GCC. The try block and all handlers are inside the |
---|
| 433 | block. When they are complete control exits the block and the empty object |
---|
| 434 | is cleaned up, which runs the function that contains the finally code. |
---|
| 435 | |
---|
| 436 | \section{Cancellation} |
---|
| 437 | % Stack selections, the three internal unwind functions. |
---|
| 438 | |
---|
| 439 | Cancellation also uses libunwind to do its stack traversal and unwinding, |
---|
| 440 | however it uses a different primary function \codeC{_Unwind_ForcedUnwind}. |
---|
| 441 | Details of its interface can be found in the unwind section. |
---|
| 442 | |
---|
| 443 | The first step of cancellation is to find the stack was cancelled and which |
---|
| 444 | type of stack it is. Luckily the threads library stores the main thread |
---|
| 445 | pointer and the current thread pointer and every thread stores a pointer to |
---|
| 446 | its main coroutine and the coroutine it is currently executing. |
---|
| 447 | |
---|
| 448 | So if the the current thread's main and current coroutine do not match, it is |
---|
| 449 | a coroutine cancellation. Otherwise if the main and current thread do not |
---|
| 450 | match, it is a thread cancellation. Otherwise it is a main thread |
---|
| 451 | cancellation. |
---|
| 452 | |
---|
| 453 | However if the threading library is not linked then execution must be on the |
---|
| 454 | main stack as that is the only one that exists. So the entire check is skipped |
---|
| 455 | using the linker and weak symbols. Instead the main thread cancellation is |
---|
| 456 | unconditionally preformed. |
---|
| 457 | |
---|
| 458 | Regardless of how they are choosen afterwords the stop function and the stop |
---|
| 459 | parameter are passed to the forced unwind functon. The general pattern of all |
---|
| 460 | three stop functions is the same, they continue unwinding until the end of |
---|
| 461 | stack when they do there primary work. |
---|
| 462 | |
---|
| 463 | Main stack cancellation it is very simple. The ``transfer" is just an abort, |
---|
| 464 | the program stops executing. |
---|
| 465 | |
---|
| 466 | The coroutine cancellation stores the exception on the coroutine and then |
---|
| 467 | does a coroutine context switch. The rest is handled inside resume. Every time |
---|
| 468 | control returns from a resumed thread there is a check to see if it is |
---|
| 469 | cancelled. If it is the exception is retrieved and the CoroutineCancelled |
---|
| 470 | exception is constructed and loaded. It is then thrown as a regular exception |
---|
| 471 | with the default handler coming from the context of the resumption call. |
---|
| 472 | |
---|
| 473 | The thread cancellation stores the exception on the thread's main stack and |
---|
| 474 | then returns to the scheduler. The rest is handled by the joiner. The wait |
---|
| 475 | for the joined thread to finish works the same but after that it checks |
---|
| 476 | to see if there was a cancellation. If there was the exception is retrieved |
---|
| 477 | and the ThreadCancelled exception is constructed. The default handler is |
---|
| 478 | passed in as a function pointer. If it is null (as it is for the |
---|
| 479 | auto-generated joins on destructor call) it a default is used that simply |
---|
| 480 | calls abort; which gives the required handling on implicate join. |
---|