ZeroDDS-SHM-Transport 1.0 — Spec Coverage

A ZeroDDS-vendor-specific shared-memory transport. Analogous to Cyclone’s iceoryx integration, FastDDS SHM and RTI DDS SHM. Not OMG-normative. Implemented in:

The vendor-reserved locator-kind value (§9.4) is a constant in crates/rtps/src/wire_types.rs.

Spec family Status
OMG-normative DDSI-RTPS 2.5 §9.4 LocatorKind (vendor-reserved range) — locator value in crates/rtps/src/wire_types.rs
ZeroDDS-own spec segment layout + SPSC ring buffer + crash recovery — zerodds-shm-transport-1.0.md

§1 Scope and spec status

§1.1 What OMG standardizes

For SHM, DDSI-RTPS 2.5 standardizes only:

  • §9.4 LocatorKind: vendor-reserved values for non-IP transports. The ZeroDDS value is in crates/rtps/src/wire_types.rs.

No normative wire format, no normative segment layout, no normative cleanup protocol.

§1.2 What OMG does not standardize

  • Segment layout: vendor-specific.
  • Synchronization model (SPSC / SPMC / mutex): vendor-specific.
  • Crash recovery: vendor-specific.
  • Cleanup mechanics: vendor-specific.
  • Multi-reader distribution: vendor-specific.

§1.3 ZeroDDS choice

The ZeroDDS SHM transport defines its own spec (this file) for segment layout + synchronization. The spec is:

  • OMG-conformant at the locator level (§9.4 vendor-reserved value).
  • Vendor-specific at the wire/synchronization level (analogous to iceoryx/FastDDS-SHM/RTI).

§2 Segment layout

  offset 0:   magic: u32 BE   "ZSHM"  (0x5A53484D)
  offset 4:   version: u32 LE
  offset 8:   capacity: u64 LE         (data region, excluding header)
  offset 16:  head: AtomicU64          (next write offset, writer-owned)
  offset 24:  tail: AtomicU64          (next read offset, reader-owned)
  offset 32:  shutdown: AtomicU32      (0=active, 1=owner-gone)
  offset 36:  reserved (padding to a 64-byte cache line)
  offset 64:  data region [capacity bytes]
  • Magic "ZSHM" — a version discriminator; rejects foreign segments.
  • Version: currently 1. Bumped on a layout change; openers reject unknown versions.
  • Head/tail: AcqRel atomics for lock-free single-producer single-consumer synchronization.
  • Shutdown: an owner→consumer termination signal (the owner sets it to 1 in Drop).

Repo anchors: crates/transport-shm/src/posix.rs::HEADER_BYTES, SHM_MAGIC, SHM_VERSION.

§3 Frame format

A length-prefix format inside the data region:

+---------+---------+---------+---------+----- ...
| len: u32 LE                            | bytes [len]
+---------+---------+---------+---------+----- ...
  • len = 0xFFFF_FFFE marks a padding frame (a ring-end marker). The writer inserts it when there is not enough contiguous space at the ring end; it then jumps to the start.
  • len < capacity is a data frame.

Repo anchors: posix.rs::PADDING_FRAME_LEN, posix.rs::SegmentLayout::push_frame, posix.rs::SegmentLayout::pop_frame.

§4 Synchronization model

§4.1 Single-producer single-consumer

One segment per (owner, consumer) pair — not one segment per owner with a multi-reader fan-out.

Rationale: - Lock-free SPSC scales linearly with the reader count, with no global contention. - A pthread_mutex with PTHREAD_PROCESS_SHARED would be the alternative, but it is crash-recovery-fragile. - SPMC (like iceoryx) blocks the writer on the slowest reader — bad with heterogeneous readers.

Cost: N segments for N readers. With 100 readers × 1 MiB default = 100 MiB. Acceptable; the per-pair segment size is configurable.

§4.2 Memory ordering

  • Writer: Release store on head after the frame write.
  • Reader: Acquire load of head before the frame read.
  • Guaranteed: the writer-side frame bytes are visible as soon as the reader sees the new head value.

Repo anchors: posix.rs::SegmentLayout::head / SegmentLayout::tail.

§5 Cleanup semantics

§5.1 Predictable os_id

segment_os_id(owner, consumer) returns a deterministic segment name (/zd-<owner>-<consumer> or /zd-<owner-tail15>-<consumer-tail15> on the macOS PSHMNAMLEN).

Repo anchor: posix.rs::segment_os_id.

§5.2 Crash recovery

Before every owner create(), shm_unlink(os_id) is called. This: - reclaims zombie segments of a crashed owner. - is idempotent (ENOENT is ignored). - prevents a system-wide /dev/shm leak.

Repo anchor: posix.rs::shm_unlink_by_os_id.

§5.3 Shutdown flag

The owner sets shutdown = 1 in Drop (Release store). The consumer checks the flag in wait_for_frame after every empty poll and returns with a targeted error (Io{message:"shm owner terminated"}) instead of falling blindly into recv_timeout.

Repo anchors: posix.rs::SegmentLayout::set_shutdown, posix.rs::SegmentLayout::is_shutdown.

§5.4 Race protection on owner create

An exclusive whole-file lock on a sentinel file serializes parallel owner creates on the same os_id — across threads AND processes. Linux/macOS via flock(LOCK_EX), Windows via LockFileEx (LOCKFILE_EXCLUSIVE_LOCK, blocking). Both auto-release on handle close / process death (identical crash-resilience).

Repo anchors: posix.rs::acquire_flock_excl, posix.rs::FlockGuard.

§6 Platform support

Platform Status Notes
Linux ✅ primary full test coverage
macOS ✅ supported PSHMNAMLEN limit observed
Windows ✅ supported zero-copy SHM via shared_memory (CreateFileMapping); owner-create race via LockFileEx; cleanup via OS handle reference counting. Test suite green on Windows (19/19, incl. open_concurrent_two_threads_both_bound)
no_std not supported std-only (mmap needs OS calls)

§7 Test coverage

Spec section Tests
§2 segment layout posix.rs::tests::magic_and_layout_*
§3 frame format posix.rs::tests::push_pop_*, padding_*
§4 SPSC synchronization posix.rs::tests::concurrent_*
§5.2 crash recovery posix.rs::tests::recovers_zombie_segment
§5.3 shutdown flag posix.rs::tests::owner_drop_signals_consumer
§5.4 race protection posix.rs::tests::flock_*
§6 cross-process tests/l1_cross_process.rs

Total: 19 lib + 1 integration = 20 tests. All green on Linux, macOS and Windows (cargo test -p zerodds-transport-shm).

§8 Status

Fully covered. The ZeroDDS SHM transport is a complete, internally coherent spec; all § sections are implemented and tested. Platform support: Linux (primary), macOS and Windows — all three with a green test suite.

ZeroDDS-SHM-Transport 1.0 — Spec-Coverage

ZeroDDS-vendor-spezifischer Shared-Memory-Transport. Analog zu Cyclone’s iceoryx-Integration, FastDDS-SHM und RTI-DDS-SHM. Nicht OMG-normativ. Implementiert in:

Der vendor-reservierte Locator-Kind-Wert (§9.4) ist eine Konstante in crates/rtps/src/wire_types.rs.

Spec-Family Status
OMG-normativ DDSI-RTPS 2.5 §9.4 LocatorKind (vendor-reserved range) — Locator-Wert in crates/rtps/src/wire_types.rs
ZeroDDS-eigene Spec Segment-Layout + SpSc-Ringbuffer + Crash-Recovery — zerodds-shm-transport-1.0.md

§1 Scope und Spec-Status

§1.1 Was OMG normiert

DDSI-RTPS 2.5 normiert für SHM nur:

  • §9.4 LocatorKind: vendor-reservierte Werte für nicht-IP- Transports. ZeroDDS-Wert in crates/rtps/src/wire_types.rs.

Kein normatives Wire-Format, kein normatives Segment-Layout, kein normatives Cleanup-Protokoll.

§1.2 Was OMG nicht normiert

  • Segment-Layout: vendor-spezifisch.
  • Synchronisations-Modell (SpSc / SpmC / Mutex): vendor-spezifisch.
  • Crash-Recovery: vendor-spezifisch.
  • Cleanup-Mechanik: vendor-spezifisch.
  • Multi-Reader-Distribution: vendor-spezifisch.

§1.3 ZeroDDS-Wahl

ZeroDDS-SHM-Transport definiert eine eigene Spec (diese Datei) für Segment-Layout + Synchronisation. Die Spec ist:

  • OMG-konform auf Locator-Ebene (§9.4 vendor-reservierter Wert).
  • Vendor-spezifisch auf Wire-/Synchronisations-Ebene (analog iceoryx/FastDDS-SHM/RTI).

§2 Segment-Layout

  offset 0:   magic: u32 BE   "ZSHM"  (0x5A53484D)
  offset 4:   version: u32 LE
  offset 8:   capacity: u64 LE         (Daten-Region, ohne Header)
  offset 16:  head: AtomicU64          (nächster Schreib-Offset, Writer-owned)
  offset 24:  tail: AtomicU64          (nächster Lese-Offset, Reader-owned)
  offset 32:  shutdown: AtomicU32      (0=active, 1=owner-gone)
  offset 36:  reserved (padding zu 64-Byte cache-line)
  offset 64:  data-region [capacity bytes]
  • Magic "ZSHM" — Versions-Discriminator, lehnt fremde Segmente ab.
  • Version: aktuell 1. Bump bei Layout-Änderung; Opener lehnen unbekannte Versionen ab.
  • Head/Tail: AcqRel-Atomics für Lock-free Single-Producer-Single- Consumer-Synchronisation.
  • Shutdown: Owner→Consumer-Termination-Signal (Owner setzt auf 1 in Drop).

Repo-Anker: crates/transport-shm/src/posix.rs::HEADER_BYTES, SHM_MAGIC, SHM_VERSION.

§3 Frame-Format

Length-Prefix-Format innerhalb der Daten-Region:

+---------+---------+---------+---------+----- ...
| len: u32 LE                            | bytes [len]
+---------+---------+---------+---------+----- ...
  • len = 0xFFFF_FFFE markiert ein Padding-Frame (Ring-End-Marker). Writer setzt es ein, wenn nicht genug zusammenhängender Space am Ring-Ende ist; springt danach an den Anfang.
  • len < capacity ist ein Daten-Frame.

Repo-Anker: posix.rs::PADDING_FRAME_LEN, posix.rs::SegmentLayout::push_frame, posix.rs::SegmentLayout::pop_frame.

§4 Synchronisations-Modell

§4.1 Single-Producer-Single-Consumer

Ein Segment pro (owner, consumer)-Paar — nicht ein Segment pro Owner mit Multi-Reader-Fan-out.

Rationale: - Lock-free SpSc skaliert linear mit Reader-Count, keine globale Contention. - pthread_mutex mit PTHREAD_PROCESS_SHARED wäre der Alternativweg, ist aber crash-recovery-fragile. - SpmC (wie iceoryx) blockt den Writer am slowest-Reader — bei heterogenen Readern schlecht.

Preis: N Segmente bei N Readern. Bei 100 Readern × 1 MiB Default = 100 MiB. Akzeptabel; Segment-Größe pro Paar konfigurierbar.

§4.2 Memory-Ordering

  • Writer: Release-Store auf head nach Frame-Write.
  • Reader: Acquire-Load von head vor Frame-Read.
  • Garantiert: Writer-side Frame-Bytes sind sichtbar, sobald Reader den neuen head-Wert sieht.

Repo-Anker: posix.rs::SegmentLayout::head / SegmentLayout::tail.

§5 Cleanup-Semantik

§5.1 Predictable os_id

segment_os_id(owner, consumer) liefert einen deterministischen Segment-Namen (/zd-<owner>-<consumer> bzw. /zd-<owner-tail15>-<consumer-tail15> auf macOS-PSHMNAMLEN).

Repo-Anker: posix.rs::segment_os_id.

§5.2 Crash-Recovery

Vor jedem Owner-create() wird shm_unlink(os_id) gerufen. Dies: - Räumt Zombie-Segmente eines crashed Owners auf. - Ist idempotent (ENOENT wird ignoriert). - Verhindert systemweiten /dev/shm-Leak.

Repo-Anker: posix.rs::shm_unlink_by_os_id.

§5.3 Shutdown-Flag

Owner setzt shutdown = 1 in Drop (Release-Store). Consumer prüft das Flag in wait_for_frame nach jedem leeren Poll und kehrt mit einem gezielten Error (Io{message:"shm owner terminated"}) zurück, statt blind in den recv_timeout zu fallen.

Repo-Anker: posix.rs::SegmentLayout::set_shutdown, posix.rs::SegmentLayout::is_shutdown.

§5.4 Race-Protection beim Owner-Create

Eine exklusive Whole-File-Lock auf einer Sentinel-Datei serialisiert parallele Owner-Creates auf dieselbe os_id — über Threads UND Prozesse. Linux/macOS via flock(LOCK_EX), Windows via LockFileEx (LOCKFILE_EXCLUSIVE_LOCK, blockierend). Beide werden beim Schließen des Handles bzw. Prozess-Tod automatisch freigegeben (gleiche Crash-Resilienz).

Repo-Anker: posix.rs::acquire_flock_excl, posix.rs::FlockGuard.

§6 Plattform-Support

Plattform Status Anmerkungen
Linux ✅ primary Volle Test-Coverage
macOS ✅ supported PSHMNAMLEN-Limit beachtet
Windows ✅ supported Zero-Copy-SHM über shared_memory (CreateFileMapping); Owner-Create-Race via LockFileEx; Cleanup über OS-Handle-Reference-Counting. Test-Suite grün auf Windows (19/19, inkl. open_concurrent_two_threads_both_bound)
no_std nicht supported std-only (mmap braucht OS-Calls)

§7 Test-Coverage

Spec-Sektion Tests
§2 Segment-Layout posix.rs::tests::magic_and_layout_*
§3 Frame-Format posix.rs::tests::push_pop_*, padding_*
§4 SpSc-Synchronisation posix.rs::tests::concurrent_*
§5.2 Crash-Recovery posix.rs::tests::recovers_zombie_segment
§5.3 Shutdown-Flag posix.rs::tests::owner_drop_signals_consumer
§5.4 Race-Protection posix.rs::tests::flock_*
§6 Cross-Process tests/l1_cross_process.rs

Total: 19 lib + 1 integration = 20 Tests. Alle grün auf Linux, macOS und Windows (cargo test -p zerodds-transport-shm).

§8 Status

Voll abgedeckt. ZeroDDS-SHM-Transport ist eine vollständige, in-sich-kohärente Spec; alle §-Sektionen sind implementiert und getestet. Plattform-Support: Linux (primary), macOS und Windows — alle drei mit grüner Test-Suite.