lib/machine/src/checkpoint/hot/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 //! Recording a running machine often costs too much when every capture copies
 2 //! and hashes all 67,108,864 bytes, because an execution changes only a small
 3 //! part of that data between two captures. The machine's fixed 67,108,864
 4 //! bytes, addressed from zero, holding 16,384 pages, are its *memory*. A memory
 5 //! image whose page tables have been rewritten to their canonical form and
 6 //! whose boot frame, request ring, event ring, and kernel stack are zeroed is
 7 //! *normalized memory*. A checkpoint holding a complete normalized memory image
 8 //! in two caller-owned regions is a *durable checkpoint*. A block of 4096
 9 //! contiguous bytes of memory, named by its zero-based index, is a *page*. The
10 //! calls here record only the pages that differ from a durable checkpoint
11 //! already written down. A page whose bytes differ from the parent image's page
12 //! at the same index is a *changed page*. Changed pages recorded as strictly
13 //! ascending indices with one matching 4096-byte page record per index are
14 //! *ordered changed pages*. A checkpoint holding ordered changed pages against
15 //! a durable parent is a *hot snapshot*.
16 //!
17 //! A partial record is worth having only when it still yields the name the full
18 //! image would carry. This code takes from no outside source: it takes its
19 //! digests from the sibling digest schema inside this package. The complete
20 //! binary tree over the 16,384 page digests, 14 levels deep, is the *page
21 //! tree*. The SHA-256 identity of a normalized memory image, binding the page
22 //! tree's root to the fixed memory geometry, is the *memory digest*. Folding
23 //! the changed pages into the same page tree produces the same memory digest as
24 //! the full image.
25 //!
26 //! A snapshot borrows its parent handle and two caller-owned arrays, one for
27 //! ordered page indices and one for the matching page bytes. The caller's array
28 //! length fixes how many changed pages fit, and a capture that would exceed it
29 //! leaves both arrays unchanged.
30 //!
31 //! The memory image of a running machine, before normalization, is its *live
32 //! memory*. Capture checks the parent relationship and the live memory before
33 //! it writes anything into those arrays.
34 //!
35 //! A page table, boot frame, request ring, event ring, or stack page, which a
36 //! capture takes from the parent, is a *retained page*. Page tables, the boot
37 //! frame, the transport rings, and the stack keep their parent bytes, so
38 //! per-run state never enters a snapshot as a changed page.
39 //!
40 //! Restore starts from the parent's memory already present in the destination,
41 //! and the snapshot requires that memory to hash to the parent's memory digest
42 //! before it writes anything.
43 //!
44 //! Restore then lays each changed page over that memory and hashes the result,
45 //! comparing it with the memory digest the snapshot recorded.
46 
47 const owner = @import("owner.zig");
48 
49 pub const Error = owner.Error;
50 pub const Capacity = owner.Capacity;
51 pub const Materialized = owner.Materialized;
52 pub const Snapshot = owner.Snapshot;
53 pub const Storage = owner.Storage;
54 pub const capture = owner.capture;
55 pub const maximum_capacity = owner.maximum_capacity;
56 pub const page_bytes = owner.page_bytes;
57 pub const page_count = owner.page_count;