The plan is to use this C code directly with PyPy, and not write
manually the many calls to the shadow stack and the barrier functions.
But the manual way is possible too, say when writing a small interpreter
directly in C.

The commands sigon and sigoff enable and disable SIGSEGV-handling. lon
and loff enables and disables stopping of other threads while stepping through
one of them. After reaching a breakpoint in GDB, I usually run sigon and lon
to enable GDB to handle real SIGSEGV (e.g., while printing) and to stop other
threads.

runloop re-runs a program until there is a crash (useful for reproducing rare
race conditions).

Furthermore, there are some useful GDB extensions under /c7/gdb/gdb_stm.py
that allow for inspecting segment-local pointers. To enable them, add the
following line to your .gdbinit:

python exec(open('PATH-TO-STMGC/c7/gdb/gdb_stm.py').read())

Building PyPy-STM

The STM branch of PyPy contains a copy of the STMGC library. After changes to
STMGC, run the import_stmgc.py script in /rpython/translator/stm/. In the
following, / is the root of your PyPy checkout.

The Makefile expects a gcc-seg-gs executable to be on the $PATH. This
should be a GCC that is either patched or a wrapper to GCC 6.1 that passes
the necessary options. In my case, this is a script that points to my custom
build of GCC with the following content:

The usession-folder will keep the produced C source files. You will need
them whenever you do a change to the STMGC library only (no need to
retranslate the full PyPy). In that case:

Go to ~/pypy-usession/usession-stmgc-c8-$USER/testing_1/

make clean && make -j8 will rebuild all C sources

Faster alternative that works in most cases: rm ../module_cache/*.o
instead of make clean. This will remove the compiled STMGC files,
forcing a rebuild from the copy in the /rpython/translator/stm
folder.

The script puts a pypy-c into /pypy/goal/ that should be ready to run.

Log tools

STMGC produces an event-log, if requested. Some tools to parse and analyse these
logs are in the PyPy repository under /pypy/stm/. To produce a log, set the
environment variable PYPYSTM to a file name. E.g.:

env PYPYSTM=log.pypystm pypy-c program.py

and then see some statistics with

/pypy/stm/print_stm_log.py log.pypystm

Benchmarks

In PyPy's benchmark repository (https://bitbucket.org/pypy/benchmarks) under
multithread is a collection of multi-threaded Python programs to measure
performance.

One way to run them is to check out the branch multithread-runner and do the
following:

./runner.py pypy-c config-raytrace.json result.json

This will use the configuration in the JSON file and run a few iterations; then
write the result into a JSON file again. It will also print the command-line
used to run the benchmark, in case you don't want to use the runner. The
getresults.py script can be used to compare two versions of PyPy against each
other, but it is very limited.