Style Guide =========== If you read the GNU Coding Standards as well as the Indian Hill style guide, you will probably understand many of the decisions I've made. C has great potential for abuse and short-term hacks, but if you program as simply as possible following a fairly strict style, things actually get easier and a nicer design tends to fall out of it. * Don't use function macros except for constant initialization. * Don't call functions as arguments to other functions; call the function first on a separate line and assign the value to a temporary. * Don't pass values by reference in order to return two values. * Let each object worry only about its own state. * Assert parameters are safe in a method prologue. * Don't bother testing that specific assertions fail. * Use '(spmt_word_t) 0x1' instead of '(unsigned) 0x1' * Don't unit test behaviour of other libraries (e.g. malloc). * Create tests for any #defines that could be computed, e.g. SPMT_WORD_ALIGNMENT. * When two parameters always appear together, create a struct for them and pass a pointer to the struct. * One module per struct. Always use opaque types. * Start new modules from tests/template.c, src/template.* * Don't use global variables ever, since the library might one day be called by more than one client at a time. * Everything that moves into libspmt must get a unit test. * One call to fail_q, fail_unless_q, or fail_if_q per unit test. * Object fields written inside critical sections but read outside of critical sections must be volatile; use spmt_atomic_t. * Don't create local variables from pointers in order to "mitigate the cost of multiple pointer dereferences". The compiler will take care of this, and the locals make refactoring more difficult. * Runtime checks are the only things that should appear inside #ifndef NDEBUG ... #endif /* !NDEBUG */, and at that only if they're too big or complicated for assert(). Constants ========= * Use enums when a series of consecutive values is desired. * Use static const = for constants. -- Exception: use enum { = } when is an array size. * Use #define when the constant is visible between modules but there is no need for external linkage outside of the library. Library Design ============== The library is composed of modules, one per data type. Types are opaque, declared in the module .h file and defined in the module .c file. There are 3 visibility levels for library data: PUBLIC, LIBRARY, and PRIVATE. These govern the location of function prototypes, constants, typedefs, and defines. visibility data PUBLIC spmt.h LIBRARY module .h file PRIVATE module .c file The spmt.h file gets installed into a system directory and is available for use by the client. Since the library API is relatively small, there are no other .h files installed. Internally, private.h includes all library header files. Thus, library modules need only include private.h to access all other data with library or public visibility. In the future, spmt.c can include all module .c files. This will allow inter-module global optimization. It will also allow us to make all library functions static---static functions must have their declaration and definition in the same file to prevent gcc's -Wunused flag from issuing a warning. Migration ========= Replacing SableSpMT functionality with libspmt calls can be done by isolating the old component interface with a wrapper, and then redirecting calls to libspmt. This also allows for fairly easy comparison of the two components. Externally Visible Functionality ================================ This library will support: dependence buffering prediction stack buffering dynamic statistics gathering thread management Buffer Notes ============ If the client tries to read from an invalid address, it should invalidate the speculative thread and not the dependence buffer. However, maybe some kind of `valid memory region' support would be nice in the library, since presumably each client will want it. Client single-instruction rollback can be quite difficult when it comes to detecting invalid buffer operations, because many steps might be involved in computing an address. Could be much easer to invalidate the buffer. The buffer in SableSpMT had four possible states: OK, OVERFLOW, FIELD_OUTSIDE_HEAP, and INVALID (dependence error). For profiling reasons it is nice to keep all of these states around. Predictor Notes =============== We have separate last value, stride, 2-delta stride, context, and memoization predictor objects. The hybrid predictor aggregates them.