Solution (source code)

= Solution

Separate the two required orders. A writer must make all initialization <store instructions> to a fresh version visible before another <CPU core> can use the publication of its address. A reader must load `p` before the <load instructions> of fields addressed through the saved <pointer>. Assume ordinary coherent cacheable <computer memory>, atomic aligned pointer accesses, immutable published versions, and the lifetime guarantee from part (ii). The sequences below are architectural operations; a <compiler> must preserve the stated accesses and dependencies.

\b[TSO.] <Total store order> preserves store-to-store order, so initialization writes cannot become visible after the later pointer publication. It also preserves load-to-load order, so reading the pointer precedes reading its fields. Its store-to-load relaxation, illustrated in part (b), does not break either required ordering. Therefore
$$
\boxed{\text{TSO: no additional hardware fence is needed for this publication pattern}.}
$$
No drain of every reader's <store buffer> and no explicit cache flush is required. This statement is about hardware ordering; unsynchronized ordinary C or C++ accesses to `p` would still need the language's <atomic operation> and <acquire-release synchronization> facilities to avoid a <data race> and unwanted <compiler> transformations.

\b[Power/ARM.] These weaker <memory models> can expose a new pointer before all the writer's initialization <store instructions> are visible. Put a write-ordering <memory barrier> between the last initialization write and the store of `p`. A sufficient sequence uses `lwsync` on <POWER architecture> or an appropriately scoped `DMB`, such as `DMB ISH`, on the ARMv7 <ARM architecture family>:
``
writer:
    STORE [new + field1], value1
    STORE [new + field2], value2
    publication_barrier
    STORE [p], new
``
The scope must include every participating <CPU core>. A broader full barrier is sufficient but can cost more. Without the writer barrier, observing the new `p` and stale initialization data is exactly the unwanted message-passing outcome.<Understanding POWER Multiprocessors (2011)>[§§2.1–2.2, message passing and ordering by `sync`/`lwsync`, printed pp. 2–4]{ref}

For the reader as actually specified, the saved <pointer> is an <address dependency>: the loaded value directly determines each subsequent field's <memory address>.
``
reader:
    q := LOAD [p]
    a := LOAD [q + field1_offset]
    b := LOAD [q + field2_offset]
``
Both <POWER architecture> and the relevant ARM <memory models> respect such dependent reads. Thus \b[no additional reader hardware fence is needed when every data access retains this real address dependency]. The writer's publication barrier together with the dependent reads supplies the necessary ordering. A mere test of `p` followed by unrelated fixed-address reads would be a <control dependency>, which is not sufficient here.<Understanding POWER Multiprocessors (2011)>[§2.2, “Using dependencies” and “Control dependencies, observable speculative reads, and isync”, printed p. 3]{ref}

If that <address dependency> is not retained, use an acquire operation or an explicit read-ordering <memory barrier> after loading `p` and before reading fields. `DMB ISH` on ARMv7 or `lwsync` on <POWER architecture> is a conservative sufficient choice for this load-to-load ordering; a suitable conditional branch followed by `isync` is another POWER acquire implementation. On later ARM instruction sets an acquire <load instruction> can express the reader requirement directly. Such stronger forms are often convenient even though they are not minimal for the dependent sequence in this question.

|| Model
|| Before publishing `p`
|| After reading `p`

| <Total store order>
| No extra hardware fence
| No extra hardware fence

| Power/ARM, genuine dependent field reads
| Write-ordering publication barrier
| Address dependency suffices

| Power/ARM, general reads without the dependency
| Write-ordering publication barrier
| Acquire or sufficient read-ordering barrier

\b[The minimal answer is a writer publication barrier on Power/ARM, with the stated reader's address dependence doing the read-side ordering; TSO needs neither extra hardware fence.] None of these choices repairs an invalid <pointer>, premature <memory reclamation>, or a <lost update> between writers.