|
CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
|
Phase 2: CONCURRENT + CROSS-PROCESS fuzz of the ProcessMemory ring. More...
#include "ProcessMemory.h"#include "MemoryManager.h"#include "ThreadManager.h"#include "UnitTestFramework.h"#include <map>#include <vector>#include <stdlib.h>#include <string.h>#include <unistd.h>Go to the source code of this file.
Classes | |
| struct | cmlabs::ConcRand |
| Deterministic xorshift64* — same as Phase 1 so seeds behave comparably. More... | |
| struct | cmlabs::ConcOracle |
| struct | cmlabs::ConcCtx |
Namespaces | |
| namespace | cmlabs |
Functions | |
| static uint32 | cmlabs::ConcEnvU32 (const char *name, uint32 def) |
| static bool | cmlabs::ConcEnvFlag (const char *name) |
| static uint32 | cmlabs::ConcChecksum (const char *p, uint32 len) |
| FNV-1a — identical to Phase 1's so payload checks are comparable. | |
| static void | cmlabs::ConcFillPayload (char *buf, uint32 len, uint32 serial) |
| static DataMessage * | cmlabs::ConcMakeMsg (uint32 serial, uint32 len, uint32 &sumOut) |
| Build one message carrying its own serial + payload, so a reader can re-derive what it SHOULD have received and prove corruption rather than infer it. | |
| static THREAD_RET THREAD_FUNCTION_CALL | cmlabs::ConcWriter (THREAD_ARG arg) |
| static THREAD_RET THREAD_FUNCTION_CALL | cmlabs::ConcReader (THREAD_ARG arg) |
| static THREAD_RET THREAD_FUNCTION_CALL | cmlabs::ConcResizer (THREAD_ARG arg) |
| Tier C helper: grow the segment repeatedly while readers are live, so resize() unmaps and repoints header underneath them. | |
| static bool | cmlabs::ConcCrossProcessChild () |
| Tier B child half: open() the existing segment and drain, appending every serial read. | |
| static bool | cmlabs::ConcRunThreaded (const char *label, uint32 readers, uint32 msgs, uint32 payload, uint32 burst, uint64 seed, bool resizeStress, bool blockingReads, bool dupSelftest, bool lostSelftest) |
| Run one in-process tier. | |
| static bool | cmlabs::ConcRunCrossProcess (uint32 msgs, uint32 payload, uint64 seed) |
| Tier B: two OS processes on one segment. | |
Phase 2: CONCURRENT + CROSS-PROCESS fuzz of the ProcessMemory ring.
Phase 1 (ProcessMemoryFuzz.cpp) is deliberately single-process/single-threaded so a failing seed replays byte-for-byte. It is green over 12.8M+ ops on Linux AND macOS, which clears the ring's integer arithmetic — and clears nothing else.
This file covers the dimension Phase 1 excludes. It was written to hunt the BakeLive Anomaly (
Tier A MULTIPLE READER THREADS on ONE queue. PsySpace::threadPoolDispatch runs a thread POOL, all calling waitForMsgQ on the same queue. waitForQ gates on if (qHeader->count), reads at startPos, then advances it — so if two readers could straddle that gate, one message would be returned TWICE while startPos advanced ONCE. Result: clean, up to 16 concurrent readers. Tier A' BURST-DRAIN: fill to ~64 entries at the real 2314-byte message size, then let the readers drain the lot at once. This reproduces the shape of the failing case rather than a random op mix. Result: clean, to 100k messages. Tier B TWO OS PROCESSES on one segment: the real contended cross-process mutex and two independent header mappings. Result: clean. Tier C resize() UNDER A CONCURRENT READER. resize() does not grow in place: it creates a new segment, memcpy's, unmaps the old one and repoints header, and waitForQ's fast path (queue non-empty on entry) skips the re-fetch its wait path performs. Result: clean. Tier D THE BLOCKING PATH. Phase 1 only reads when its model is non-empty, so waitForQ never waits on the named semaphore, never releases the mutex mid-call and never re-enters. Result: clean.
⚠️ ORACLE STRENGTH IS LOWER THAN PHASE 1, ON PURPOSE. With concurrent readers there is no total order to check against, so this cannot assert sequence. It asserts SET equality: every serial written is read exactly once, payload intact. A green result here is therefore weaker evidence than a green Phase 1 — say so when reporting it.
Every checker has a positive control that MUST fail (PSY_CONC_*SELFTEST), following the Phase 1 convention. That convention matters: the BakeLive investigation lost far more time to FOURTEEN separate instrument defects than to the bug itself, and the ones caught early were caught by controls. Run the controls before trusting a green result.
Env: PSY_CONC_TIER=A|A2|B|C|D|ALL which tier (default ALL; A2 is the burst-drain tier) PSY_CONC_READERS=<n> reader threads for tier A/C (default 4) PSY_CONC_MSGS=<n> messages per run (default 20000) PSY_CONC_BURST=<n> tier A' burst size; 0 = steady mix (default 64) PSY_CONC_PAYLOAD=<n> payload bytes, 0 = mixed (default 2280 ~ the real 2314-byte wire size) PSY_CONC_SEED=<n> RNG seed (default 0x2000) PSY_CONC_DUPSELFTEST=1 inject a duplicate -> MUST fail PSY_CONC_LOSTSELFTEST=1 inject a loss -> MUST fail PSY_CONC_CHILD=<mode> INTERNAL: re-exec entry point for tier B
Definition in file ProcessMemoryConcFuzz.cpp.