The Relaxed Memory Model Zoo
Mapping the space of weak memory models
There are today around a hundred published memory models. They span 47 years, from Lamport’s sequential consistency in 1979 to the models published this year; they cover CPUs, GPUs, languages, and persistent and transactional memory; and they were written by communities that cite each other unevenly. Trying to compare models — is Weakestmo weaker than C11, or incomparable to it? — means reading several papers and reconstructing a containment argument that none of them states.
Many publications on verification in a relaxed-memory setting claim genericity
by parameterising their algorithms by the memory model, only to then assume
that the model is specifiable in cat [1],
or that it forbids specific shapes such as thin-air cycles. Finding out which
weak memory models are admitted or excluded by such an assumption then requires
either a broad literature search or digging through repositories of weak memory
model specifications [2].
I wrote the Relaxed Memory Model Zoo — the Zoo from now on — as a living survey document which catalogues weak memory models with their properties and the relations between them, and also makes that catalogue accessible and searchable for weak memory researchers. Every model and every edge carries provenance information naming the original publication. Where a relation rests on litmus evidence, the tests that support it ship with it. A time slider makes the chronological development of the field explorable, opening the area up to historians of computing as well. The dataset behind the graph is machine-readable, which makes targeted exploration of weak memory behaviours with algorithmic implementations possible. The screenshot below is taken from the Zoo at rmm-zoo.kissig.org.
Execution is not in the order you wrote
In a weak memory setting, memory accesses can become observably out of order: another thread can see them take effect in an order contradicting the order the program is written in. On machines that are not multi-copy atomic, it goes further still: two observer threads can disagree with each other about the order of the same two writes.
Reordering is the common case but not the only one. Eliminating a redundant
access, forwarding a value into a register, and — at the pathological end —
producing a value with no origin at all belong to the same family: things an
implementation may do to your program that its text does not obviously permit.
The example below shows how gcc 15.2 -O2 on x86-64 eliminates the first of
two ordinary stores to the same variable:
Which modifications an implementation may make is neither arbitrary nor a matter of cleverness — it is written down, in a memory consistency model.
The contract that binds a program to its execution
A memory consistency model is the contract that binds a program to its execution. Adve and Gharachorloo call it “an interface between the programmer and the system”, one that needs a specification at every level of that interface — machine code as much as high-level language [3]. The contract reading is Adve and Hill’s: they re-define weak ordering as “a contract between software and hardware”, in which software agrees to formally specified constraints and hardware agrees to appear sequentially consistent to at least the software that obeys them [4].
The contract is between three parties: it tells the programmer what they may assume about what other threads can observe, the compiler which transformations are sound with respect to the desired target, and the hardware which reorderings and buffering it may perform.
Each party’s freedom is another’s obligation, which is why most of the Zoo’s property columns describe transformations — whether a reordering, an elimination or a value-forwarding step is sound under the model. A compiler writer reads such a column as the optimisations they may apply, a hardware architect as the reorderings the machine may perform, and a programmer as a guarantee they no longer have. The rest state guarantees outright: coherence, external data-race freedom, absence of undefined behaviour, multi-copy atomicity.
A model fixes the class of behaviours a program may be observed to have, not the behaviour it has. Almost every interesting concurrent program has many permitted outcomes, and the model draws the boundary of that set. This is why the natural ordering on models is set inclusion over behaviours, and why the unit of evidence is a single outcome that falls inside one boundary and outside another.
The contract is drawn at more than one boundary. A hardware model is the
contract between an ISA and its microarchitecture; a language model is the
contract between a language and its whole implementation — compiler, runtime
and hardware together. These are different models, not two statements of one:
RC11 says nothing about
ARMv8’s store buffers, and ARMv8
says nothing about what a C++ compiler may do to a non-atomic access. What a
running program actually gets is the composition of the two, and they compose
only when someone proves the compiler’s mapping from one to the other sound.
That proof is a relation between models rather than a part of either — which
is why it appears in the Zoo as its own edge type: 25 compilation edges, and
why, for instance, RC11 reaches hardware through
IMM [5] rather than directly.
Not every node on the map is a contract someone signed. SC is a reference point nobody implements; causal consistency and the session guarantees come from distributed storage; snapshot isolation and its persistent variants come from databases. They earn their place by the same test the contracts do: each fixes a set of allowed behaviours precisely enough to be compared by inclusion, and the models that are contracts are positioned against them. That is the criterion for what belongs in the Zoo — anything whose allowed behaviours can be stated sharply enough to be ordered, with a published source to attribute it to.
One program, three permissions
Follow one program through all three. On the left, three statements with
ordinary (non-atomic) accesses, in the order you wrote them. On the right, what
actually gets executed — real gcc 15.2 -O2 output for x86-64, with directives
and address setup elided:
The load is gone. The compiler forwarded the stored value into the third
statement, so the store to y no longer takes its value from x at all, and
the dependency that ran load → store in your source no longer exists in the
object code. Clang 20 does the same thing on AArch64: both str instructions
take their value from the same register, and nothing separates them.
That transformation is the compiler exercising its half of the contract, and the language model is what says it may. Notably, it is also free not to: make those same accesses relaxed atomics and neither GCC 15 nor clang 20 forwards, even though C11 permits it. Implementations are frequently stricter than the contract requires — which is why a model’s guarantees, not any compiler’s behaviour, are what you have to reason against.
Now the third signatory. After forwarding, the object code is two independent
stores, and whether another core can observe y == 1 while x is still 0 is
no longer the compiler’s business — it is the hardware model’s. On
x86-TSO it cannot: stores are not
reordered with stores, so the order you wrote survives by accident. On
ARMv8 or
POWER, where store→store is
relaxed, the second store may become visible first, and getting your order back
costs an explicit barrier.
That single question — may store→store be reordered — is one of the 28 property
columns (reorder_ss), and the reason
TSO,
PSO and ARMv8 are three different
nodes on the map rather than one. What another thread finally observes is the
composition of two permissions granted by two different documents: one the
compiler took under the language model, one the CPU took under its own. Neither
document alone predicts it.
Weak, relative to what
The word doing the work in weak memory model is a comparison to sequential consistency [6], in which every execution is some interleaving of the threads’ program orders. SC is the model nearly everyone reasons with informally, and nearly nobody implements: store buffers, caches, speculation and ordinary compiler optimisations all violate it. Every model below SC in the map keeps part of that intuition and gives up the rest. What separates them is where they draw the line — which guarantees a programmer loses so that a store buffer, a cache or an optimisation can be kept.
Language models mostly recover the intuition conditionally rather than
abandoning it: if your program is data-race-free, you are promised sequential
consistency. What happens when it is not race-free is where the contracts
genuinely diverge — undefined behaviour in C++ [7][8], a bounded
safety guarantee in Java [9], races bounded in space and time in
OCaml [10]. Two of the property columns, no_ub and edrf,
track exactly this split.
For some of the mainstream language models, this contract is known to be defective. The C11/C++20 axioms fail to forbid out-of-thin-air values that no compiler and no CPU actually produce. A substantial share of the models in the Zoo exist to close that gap, and the disagreements between them are still live — the subject of its own section below. The map is, in that sense, a picture of a contract still under negotiation — not a settled taxonomy.
Wherever a model draws its line, a litmus test pins down one point on it: a small program with an outcome reachable only if a specific relaxation is allowed.
What a litmus test looks like
A litmus test is a tiny concurrent program — usually two to four threads, a handful of accesses — together with an initial state and a question about the final state. It is not a test in the software-engineering sense. It asks whether a particular outcome is permitted, and the answer is a property of the model, not of any one run.
Here is the one the SC → TSO edge rests on, exactly as it sits in the
repository:
Four parts: the architecture and a name; the initial state (x and y both
zero); two threads, each storing to one location and then loading the other;
and the condition — the outcome we are asking about. Here it asks whether
both threads can read 0.
For both loads to return 0, each thread’s load must effectively happen before
the other thread’s store — which requires the store to be delayed past the
load. That is store→load reordering, and whether it is allowed is precisely
what separates sequential consistency from
TSO. Run the same file through
herd7 [1] under the two models:
Never 0 3 means the tool enumerated three candidate executions and none
satisfied the condition — the outcome is forbidden. Sometimes 1 3 means
one of three did — it is allowed. A store buffer, which lets a store sit in
a per-core queue while later loads proceed, is exactly the implementation that
makes the second verdict true.
The same discipline extends past herd7 where it has to: the Java and OCaml edges run under a JDK and an OCaml runtime, the thin-air edges run under MoRDor [11]. A follow-up post will show how the same tests locate a real language implementation in the lattice, using Rust as the example and running under loom, Miri and real silicon.
One test, run under two models, yields two verdicts — and that pair is the witness for a relation in the graph.
The ordering, and what an edge means
Models are ordered by the inclusion of the behaviours they allow. A → B
strictly weaker means every execution A permits, B permits too, and there
is at least one B permits that A forbids — the arrow runs from the stronger
model to the weaker one. The current dataset contains 59 strictly-weaker edges,
26 incomparable pairs, 35 equivalences and 25 compilation mappings, with 112
references spanning 1979–2026.
In the Zoo, that separation is witnessed by a test shipped with the dataset
wherever one exists. Take the store→store question the compiler example ended
on, as the Zoo’s TSO → PSO edge states it, in the message-passing shape:
P0 writes the data x and then the flag y; P1 reads the flag and then
the data. The condition asks whether P1 can see the flag set (1:X0=1) while
still reading the data as stale (1:X2=0) — the message arriving before its
contents. Run the same file under both models:
Forbidden under TSO, allowed under PSO. Without such a program the claim would be an assertion about two papers rather than a fact about two models.
A → B asserts two things: containment, that every behaviour A allows
B allows too, and strictness, that B allows at least one thing A does
not. A litmus test is an existential — it settles strictness. Containment is
universally quantified over all programs, and no finite number of tests
establishes it. The dataset therefore takes strictness from a test where one
exists, and containment from a reading of the literature — provisionally, until
a converse witness establishes otherwise. It is partial by construction, and a
work in progress.
A pair with a witness in one direction and none in the other is drawn as strictly weaker; the same pair would be incomparable if a converse witness turned up. Not finding a separating program is the current state of a search, not a proof that none exists.
What may an implementation do under this model?
In addition to answering “is A weaker than B?”, the Zoo answers “what may an implementation do under A?”. So every model also carries a property vector: 28 boolean cells in seven groups, following the framing of the survey [12], where a model is characterised by what it permits an implementation to do — which reorderings, which eliminations, which transformations survive it.
| Group | Cells | Asks |
|---|---|---|
| Compilation | 4 | is the optimal mapping to x86 / POWER / Armv7 / Armv8 sound? |
| Reordering | 4 | may adjacent accesses be reordered — Store→Load, Store→Store, Load→Load, Load→Store? |
| Elimination | 4 | may a redundant Store/Load, Store/Store, Load/Load or Load/Store pair be eliminated? |
| Other local | 7 | irrelevant load elimination, speculative load introduction, roach motel and its inverse, strengthening, trace preservation, common subexpression elimination |
| Global | 3 | register promotion, thread inlining, value-range reasoning |
| Reasoning | 5 | external DRF, coherence, no undefined behaviour, in-order execution, no out-of-thin-air |
| Atomicity | 1 | multi-copy atomicity |
Read across a row and you get a model’s profile; read down a column and you get
a map of the field on one question. Some of those columns are more interesting
than the lattice: 73 of 101 models are recorded as forbidding
out-of-thin-air, 31 as multi-copy-atomic, and 28 as offering an
external-DRF guarantee — the property most directly relevant to a programmer
who wants to reason about race-free code without reasoning about the model at
all. Those are counts of what the dataset records, not of what is true of the
field: no column is complete, and external DRF is the extreme case — 28 yes,
6 no, and two thirds of the models unrecorded. An empty cell means the
question has no answer yet, not that the answer is no.
Model properties are taken from a literature survey wherever the survey lists them: 29 of the 101 rows come straight from its tables [12]. The survey covers programming-language models, so most hardware and GPU models are outside it, and their rows are author-extrapolated — the other 72. That means the value was worked out from the model’s own definition rather than copied from a source that states it: reading the defining paper and deciding whether, say, its axioms permit store→store reordering — a judgement call rather than a quotation.
Provenance is recorded per row, as it is per edge, and the UI flags which of the two a model’s vector is. Where a cell rests on a specific result, it carries its own citation: the inverse-roach-motel column, for instance, is assigned based on the strength of Poetzl and Kroening’s soundness proof for the SC-for-DRF execution model [13], and each such cell references the result.
Out of thin air
A model that does not constrain reordering tightly enough admits behaviours no implementation ever produces. The sharpest case is a value appearing that nothing in the program ever wrote. Batty et al.’s formalisation of C++11 [8] exposed it in the mainstream language models: the standard’s prohibition on out-of-thin-air reads was informal prose that resisted formalisation, so the model as written does not actually forbid such executions — a gap they later set out in full [14]. RC11 and the models after it exist to close it.
Start from the compiler example above. The compiler kept 1 in a register and
reused it, deleting the load — and with it, the dependency that ran from the
load to the store. That is an ordinary, desirable optimisation. It is also the
root of the trouble: a syntactic dependency in your source is not a fact
about the program’s semantics, and implementations are free to discover that it
carries no information and remove it. Register caching and value forwarding are
the plain cases; common-subexpression elimination and value-range reasoning do
the same thing less visibly.
That freedom has a consequence for the specification. A model cannot simply decree “respect dependencies”, because it cannot say which ones are real without either forbidding those optimisations or reasoning about the semantics of the whole thread. The axiomatic C11/C++20 models therefore validate an execution by a weaker local condition — every read reads from some write — and that condition can be satisfied by a cycle that supports itself:
Both threads read 42, and both write 42 only because they read it. No
instruction anywhere stores 42 unconditionally — the constant does not occur
in the program except as the thing being tested for. Yet nothing in the C11
axioms rules the execution out. The value is invented out of thin air, and the
literature’s name for the phenomenon is exactly that [15].
No compiler and no processor actually does this, so the specification is strictly weaker than every implementation of it. What it costs is formal reasoning: with thin-air values permitted, you cannot prove that a value your program never wrote cannot appear — fatal for security arguments and for compositional verification, and forbidding it turns out to cost real performance [16].
The models that close the gap are among the most interesting recent ones, and they
disagree about how: the acyclic(po ∪ rf) axiom in RC11 [17], promised writes that a thread later certifies in
Promising [18], alternative executions tracked to tell a real
dependency from a false one in the event-structure models of Jeffrey and Riely
[19] and Weakestmo [20], and modularly computed dependencies in
MRD [21].
MRD is the one the Zoo’s thin-air edges are actually checked against, since
herd7 cannot construct such an execution at all.
So the most important open question in the field is precisely the one the standard tool cannot exhibit.
Where the data comes from, and what I trust it for
The models, the relations between them and the property values come from three sources: my own notes from working in the field, the survey of programming-language memory models by Moiseenko, Podkopaev and Koznov [12], and LLM-based summarisation of publications in the field. What happens to them afterwards is a pipeline with three parts:
Extraction. Large language models did the reading-at-scale: summarising
papers, surfacing candidate models worth including, pulling property values out
of the survey’s tables, and collecting the bibliographic details that became
the references block. A hundred models across 47 years of proceedings is more
than I could read.
Presentation. The web interface that renders all this — the map, its filters, the per-model pages — is written and deployed separately from the dataset.
Support. Every ordering claim in the published dataset is carried by
something a reader can check independently: a litmus test in the repository
that runs and produces the verdict, a construction argument, or a citation to
the primary source that settles it. That is what the provenance and
evidence labels record, per edge.
Extraction and support are separated because support is what confirms
extraction. They also run on different clocks: a model, an edge or a property
cell is extracted once, while the support behind it is re-checked on every
commit. A litmus test that contradicts its recorded verdict fails CI, an edge
that contradicts the transitive closure of the others fails the gate before it
can ship, the per-edge evidence label keeps a cited edge legible as cited
rather than blending into the machine-checked ones, and the structural checks
catch an edge that may be accepted in a review but does not hold.
This invites the obvious question: how much of the map is supported by evidence?
Evidence, and its absence
The Zoo is worth only as much as its provenance discipline.
Every edge carries two orthogonal labels. Provenance says where the claim
comes from: a litmus test in the repository (11 edges), a memalloy
model-comparison result (4), or the literature (130). Evidence says what
kind of thing backs it: machine_run — a tool in the repository actually
produces the verdict (40 edges); by_construction (19); or cited (86).
Only 40 out of 145 edges are currently machine-run. The reasons for the gap are:
- herd7 cannot exhibit out-of-thin-air executions, as the thin-air section
ended on. For the thin-air edges —
MRD → C11and its counterparts from sMRD, Weakestmo and CSRA — the strong side is checked in MoRDor [11] where possible, and the C11 permission is a property of the standard’s axioms, cited rather than exhibited. - Several models ship no
catmodel at all. IMM and Promising have their own artifacts (a Coq development, a dedicated tool); the survey’s research models — BMM, RMMOA, CRC, JAM, OHMM, WJES, GOS, JSMM, RMC, RAO, TSC — have none. Where a model coincides with a bundled one, it is checked through it (BMM ≡ TSO,RMMOA ≡ PSO, both fully machine-run). Otherwise the test ships with a documented verdict cited to the model’s own artifact. - Some separations are not single litmus outcomes. External-DRF reasoning guarantees and transformation-soundness differences do not reduce to one program’s outcome, and those pairs’ READMEs say so explicitly.
What is machine-run is run continuously: 65 herd7 checks, each asserting a
specific Never or Sometimes verdict, executed on every push and pull
request against a pinned herdtools7 7.58. A verdict that changes, because of a
tool upgrade for instance, fails CI.
Around that sits a consistency gate of eight checks, run before any build or
deploy. Six of them guard the data: strictly-weaker is a DAG; no pair is both
ordered and incomparable including through the transitive closure, so a
deduced order cannot contradict a drawn incomparable edge; every witness
directory matches its edge’s type and direction; and a pair exercised on both
sides shows a genuine Never + Sometimes split rather than two identical
verdicts. The other two guard the visual drawing of the map.
Applying the gate reclassified three edges originally drawn as
incomparable, after sweeps failed to produce the witness incomparability
implies: PSO ↔ POWER (every PSO-allowed behaviour I could find is
POWER-allowed, while POWER allows
load-load reordering PSO forbids), Weakestmo ↔ C11 and CSRA ↔ C11 (both are
thin-air-free repairs of C11, so they allow strictly less than it does). All
three are now strictly-weaker edges, and the history of the correction is in
the repository rather than silently overwritten.
As a research tool: finding models
I wrote the Zoo to make it possible to search over a space that is otherwise distributed across proceedings. The map filters by the language a model targets, by formalism style, by year, and by the property vectors from Moiseenko, Podkopaev and Koznov’s survey [12] — so “which models are thin-air-free, multi-copy-atomic, and support store→load reordering?” becomes a query rather than a literature review.
Cat specifiability matters for anyone mechanising. cat is the
domain-specific language in which herd7 models are written [1] — a model is a handful of definitions over the
standard relations (po, rf, co, fr, dependencies, fences) plus a few
acyclicity or irreflexivity axioms over them, and herd7 turns that description
directly into an executable checker. It is the closest thing the field has to a
common notation. Each model is therefore classified as specified (a real
cat model exists — 25 models), expressible (it could be written in cat,
but nobody has — 62), or not-expressible (it cannot be stated in cat at all
— 14, typically the operational and event-structure models, whose content is a
stepwise construction rather than a predicate over a candidate execution). That
column is a map of where the tooling stops, which is often exactly what you
want to know before starting a mechanisation.
It also answers a question that comes up constantly on the verification side. A
whole line of work is deliberately parameterised by the memory model,
because that is how it buys generality. Instead of building on one model, these
publications state their results for a class of models with assumed properties.
The Zoo turns “does this algorithm apply to my model?” into a lookup. If the
model is specified, the input the algorithm wants already exists. If it is
expressible, the algorithm applies in principle and someone has to write the
cat file first. If it is not-expressible, no amount of engineering will
make that class of technique fit, and you need a different one. Read that way,
the 25 / 62 / 14 split is a statement about the reach of an entire family of
verification algorithms: 87 of the 101 models are within it, and 14 are
structurally outside.
As an instrument: locating a real implementation
Everything so far relates published models to published models. One use case turns the dataset the other way round, and points it at a shipped implementation.
The litmus tests are not only evidence for the edges — they are a reusable instrument. Each one is a program whose outcome separates two named models, with the expected verdict on both sides written down. Port that program to a real language and run it, and the verdicts tell you which side of the edge the implementation falls on. The catalogue stops being a map of the literature and becomes a way of locating something real within the literature.
Rust is a good subject, because the question is genuinely open: it ships no
Rust.cat, and core::sync::atomic is documented to follow the C/C++ atomic
memory model, which is a statement of intent rather than a position in a
lattice. In the follow-up post I will write about how I used the Zoo’s
language-level tests on Rust atomics and probed the boundaries of loom, Miri,
herd7 and real silicon. Spoiler: they did not agree on all behaviours.
The part worth borrowing is not Rust’s position relative to the Zoo but the method. Nothing about the procedure is Rust-specific: a lattice whose edges are defined by runnable tests turns “where does this implementation sit?” from an essay question into a finite, executable checklist, and any language with atomics and a checker to run them under can be located the same way.
Guiding principles
I could have made the Zoo much bigger. Every survey or article I read named models I had not included, every paper offered another property worth tabulating, and once a language model is doing the reading for you, collecting all of it is nearly free. What stopped me was knowing the mistakes I make, and having watched the ones the models make. Both kinds are silent and hard to catch.
The question I kept returning to was not so much how many models I could collect, but how I could be certain of a relation between models or a property of a model. A litmus test gives me an existential — this model allows what that one forbids — and nothing beyond it, and no framework describes all hundred models in one vocabulary. The dataset was going to be partial whatever I did; the only real choice was whether it would say so.
The concession I find hardest is the one about containment. When I draw an edge, one direction is witnessed and the other is read out of the literature: the pair stays strictly weaker only until someone finds a program separating it the other way, at which point it is incomparable. I would rather read containment as a partial judgement than infer a total one from evidence that does not exist.
Three principles fall out of these questions:
Evidence over assertion. Every claim is supported by evidence: an edge
records how it is known and a property cell records where its value came from.
The label — machine_run, cited, by_construction, survey-sourced,
author-extrapolated — is part of the dataset.
Witnessed separation over assumed containment. A litmus test can only establish that one model allows what another forbids. The containing direction comes from a reading of the literature and stands provisionally, until a converse witness says otherwise.
Trust over completeness. An empty cell is an open question, not a no.
Unknown values stay unknown, and every count is a count of what the dataset
records rather than of what is true of the field.
Contributing, and reporting errors
I created the Zoo as a community documentation project, where facts are collected, structured, cross-checked and made publicly available. A contribution is a missing or incorrect model, property or relation, supported by a paper with a DOI, a specification, a tool artifact, or ideally executable tests.
The dataset is hosted on GitHub:
rmm-zoo-dataset —
models.json, the litmus witnesses, and the gate that guards them. Every claim
in this post is a line in that repository, and that is where contributions go.
The site that renders the data is a separate project that only consumes the
published dataset, and a new dataset version reaches it only from a tagged
release.
If you see anything wrong or missing, please report it here:
- Open an issue for anything you believe is wrong — a misclassified edge, a wrong year or attribution, a property cell that is not established by its primary source. An issue is also the right move for a model you think belongs but are unsure how to position.
- Open a pull request using the template for the kind of change: adding a model, correcting a model, correcting a relation, adding property columns, or adding litmus tests. Each template lists the data files that change together, the invariants that apply, and the regeneration steps.
CONTRIBUTING.mdcovers the dataset’s structure, the provenance and evidence vocabularies, and the checks that guard the data.- CI runs the litmus suite and the consistency gate on every push and pull request, so a change that breaks an invariant tells you before review does.
The map is live at rmm-zoo.kissig.org. If the Zoo proves useful for the community, it will get its own domain.
Conclusions
Today, over a hundred memory models exist, and almost none of the relations between them are written down anywhere. The Zoo is my attempt to collect them in one place, under a common taxonomy of relations and properties: 101 models, 145 relations, and a record on each of how it is known.
The guiding choice was trust over completeness, and that makes the Zoo partial by construction. Most relations say less than they look like they say — one direction is witnessed by a program, the other read out of the literature and standing only until someone finds the converse. Where a tool could produce the verdict, I took that over a reading of a paper: 40 of the 145 edges are machine-run, and the rest state that they are not.
Compiling the dataset has taught me about the individual models, and even more about the methodology for describing and comparing them. I hope the Zoo proves useful for the wider community as a research tool, and is taken further as a living document.
Thanks
I would like to thank Mark Batty and Dominic Orchard for discussions — and their initial scepticism. The idea of the Zoo is borrowed from the original Complexity Zoo.
References
- Alglave, Maranget, Tautschnig: Herding Cats: Modelling, Simulation, Testing, and Data Mining for Weak Memory, ACM TOPLAS, 2014 10.1145/2627752
- Alglave, Maranget et al.: herdtools7 — the herd7 distribution and its bundled catalogue of
catmodels github.com/herd/herdtools7 - Adve, Gharachorloo: Shared Memory Consistency Models: A Tutorial, IEEE Computer 29(12), 1996 10.1109/2.546611
- Adve, Hill: Weak Ordering — A New Definition, ISCA 1990 10.1145/325096.325100
- Podkopaev, Lahav, Vafeiadis: Bridging the Gap between Programming Languages and Hardware Weak Memory Models, POPL 2019 10.1145/3290382
- Lamport: How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs, IEEE Transactions on Computers, 1979 10.1109/TC.1979.1675439
- Boehm, Adve: Foundations of the C++ Concurrency Memory Model, PLDI 2008 10.1145/1375581.1375591
- Batty, Owens, Sarkar, Sewell, Weber: Mathematizing C++ Concurrency, POPL 2011 10.1145/1926385.1926394
- Manson, Pugh, Adve: The Java Memory Model, POPL 2005 10.1145/1040305.1040336
- Dolan, Sivaramakrishnan, Madhavapeddy: Bounding Data Races in Space and Time, PLDI 2018 10.1145/3192366.3192421
- Kissig: MoRDor — a tool for calculating the weak memory semantics of C programs github.com/christiankissig/mordor
- Moiseenko, Podkopaev, Koznov: A Survey of Programming Language Memory Models, Programming and Computer Software 47(6), pp. 439–456, 2021 10.1134/S0361768821060050
- Poetzl, Kroening: Formalizing and Checking Thread Refinement for Data-Race-Free Execution Models, arXiv:1510.07171, 2015 1510.07171
- Batty, Memarian, Nienhuis, Pichon-Pharabod, Sewell: The Problem of Programming Language Concurrency Semantics, ESOP 2015 10.1007/978-3-662-46669-8_12
- Boehm, Demsky: Outlawing Ghosts: Avoiding Out-of-Thin-Air Results, MSPC 2014 10.1145/2618128.2618134
- Ou, Demsky: Towards Understanding the Costs of Avoiding Out-of-Thin-Air Results, PACMPL 2 (OOPSLA), Article 136, 2018 10.1145/3276506
- Lahav, Vafeiadis, Kang, Hur, Dreyer: Repairing Sequential Consistency in C/C++11, PLDI 2017 10.1145/3062341.3062352
- Kang, Hur, Lahav, Vafeiadis, Dreyer: A Promising Semantics for Relaxed-Memory Concurrency, POPL 2017 10.1145/3009837.3009850
- Jeffrey, Riely: On Thin Air Reads: Towards an Event Structures Model of Relaxed Memory, LICS 2016 10.1145/2933575.2934536
- Chakraborty, Vafeiadis: Grounding Thin-Air Reads with Event Structures, POPL 2019 10.1145/3290383
- Paviotti, Cooksey, Paradis, Wright, Owens, Batty: Modular Relaxed Dependencies in Weak Memory Concurrency, ESOP 2020 10.1007/978-3-030-44914-8_22