Skip to documentation
SLOP

tiny.machine.checkpoint.hot

Reference tiny.machine checkpoint hot

Defined in checkpoint.

Recording a running machine often costs too much when every capture copies and hashes all 67,108,864 bytes, because an execution changes only a small part of that data between two captures.

API (18)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callscheckpointhot
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/machine/src/checkpoint/hot/owner.zig:18

zig
/// The capacity fixes how much storage a caller supplies for a capped number of/// changed pages. The byte counts cover one two-byte index and one aligned/// 4096-byte page for each slot.pub const Capacity = struct {    pages: u16,    index_storage_bytes: u32,    page_storage_bytes: u32,    /// The function derives the exact byte counts for `pages` slots. A count    /// above 16,384 returns `DeltaCapacityExceeded`.    pub fn derive(pages: usize) error{DeltaCapacityExceeded}!Capacity {        if (pages > page_count) return error.DeltaCapacityExceeded;        const index_storage_bytes = std.math.mul(            usize,            pages,            @sizeOf(u16),        ) catch return error.DeltaCapacityExceeded;        const page_storage_bytes = std.math.mul(            usize,            pages,            page_bytes,        ) catch return error.DeltaCapacityExceeded;        return .{            .pages = @intCast(pages),            .index_storage_bytes = @intCast(index_storage_bytes),            .page_storage_bytes = @intCast(page_storage_bytes),        };    }};

Source: lib/machine/src/checkpoint/hot/owner.zig:78

zig
/// The record holds the restore result from a snapshot. The `copied_pages`/// field counts the changed pages written into the caller-owned destination/// memory.pub const Materialized = struct {    material: checkpoint.Material,    copied_pages: u16,};

Source: lib/machine/src/checkpoint/hot/owner.zig:91

zig
/// The snapshot holds a changed-page checkpoint borrowing a durable parent and/// the captured storage. The caller preserves the parent, the indices, and the/// page bytes for the snapshot's lifetime.pub const Snapshot = struct {    parent: *const checkpoint.Checkpoint,    identity_value: checkpoint.Identity,    memory: checkpoint.MemoryDigest,    material: checkpoint.Material,    indices: []const u16,    pages: []align(page_bytes) const u8,    /// The function reports how many ordered changed pages the snapshot holds.    /// A caller uses this count to size a report or a later publication.    pub fn dirtyPageCount(self: *const @This()) u16 {        std.debug.assert(self.indices.len <= page_count);        return @intCast(self.indices.len);    }    /// The function revalidates the parent, the changed pages, the memory    /// digest, and the stored identity. A recomputed value differing from the    /// stored one returns `CheckpointCorrupt`.    pub fn identity(self: *const @This()) checkpoint.DurableError!checkpoint.Identity {        return (try inspect(self)).identity;    }    fn inspect(self: *const @This()) checkpoint.DurableError!Inspection {        const parent_contents = try checkpoint.inspect(self.parent);        try checkpoint.validateParent(self.material, parent_contents.material);        try checkpoint.validateDeltaImage(            self.indices,            self.material.immutable_image,        );        const memory = try checkpoint.deltaDigest(            self.parent.ram,            self.indices,            self.pages,        );        if (!std.meta.eql(memory, self.memory)) {            return error.CheckpointCorrupt;        }        const actual = try checkpoint.identify(self.material, memory);        if (!std.meta.eql(actual, self.identity_value)) {            return error.CheckpointCorrupt;        }        return .{ .parent = parent_contents, .identity = actual };    }    /// The function returns the fully verified child checkpoint root.    pub fn root(self: *const @This()) checkpoint.DurableError!checkpoint.Root {        return (try self.identity()).root;    }    /// The function verifies `expected` and requires the destination to already    /// hold the parent memory image. The snapshot storage and the destination    /// memory must be disjoint. The call returns the verified identity.    pub fn prepareForRestore(        self: *const @This(),        expected: checkpoint.Root,        destination: []align(page_bytes) const u8,    ) Error!checkpoint.Identity {        const inspection = try inspect(self);        if (!std.meta.eql(inspection.identity.root, expected)) {            return error.CheckpointRootMismatch;        }        try validateDestinationAgainst(self, destination, inspection.parent);        return inspection.identity;    }    /// The function overlays the changed pages on authenticated parent memory,    /// then verifies the child memory digest. The call returns the material and    /// the number of copied pages. Pages already copied stay in the destination    /// when the closing digest check fails.    pub fn materializeForRestore(        self: *const @This(),        expected: checkpoint.Root,        destination: []align(page_bytes) u8,    ) Error!Materialized {        const inspection = try inspect(self);        if (!std.meta.eql(inspection.identity.root, expected)) {            return error.CheckpointRootMismatch;        }        try validateDestinationAgainst(self, destination, inspection.parent);        for (self.indices, 0..) |page_index, index| {            const start = @as(usize, page_index) * page_bytes;            const source = self.pages[index * page_bytes ..][0..page_bytes];            @memcpy(destination[start..][0..page_bytes], source);        }        const restored = try checkpoint.validatedMemoryDigest(            destination,            self.material.immutable_image,        );        if (!std.meta.eql(restored, self.memory)) {            return error.MemoryDigestMismatch;        }        return .{            .material = self.material,            .copied_pages = self.dirtyPageCount(),        };    }    /// The function returns the durable parent's complete normalized memory.    pub fn evidenceRam(        self: *const @This(),    ) []align(page_bytes) const u8 {        return self.parent.ram;    }    /// The function answers whether a byte range touches the snapshot value,    /// the parent handle, the storage and memory behind that parent, or the    /// captured index and page arrays.    pub fn aliases(self: *const @This(), bytes: []const u8) bool {        return buffersOverlap(bytes, std.mem.asBytes(self)) or            buffersOverlap(bytes, std.mem.asBytes(self.parent)) or            buffersOverlap(bytes, &self.parent.storage.bytes) or            buffersOverlap(bytes, self.parent.ram) or            buffersOverlap(bytes, std.mem.sliceAsBytes(self.indices)) or            buffersOverlap(bytes, self.pages);    }};

Source: lib/machine/src/checkpoint/hot/owner.zig:50

zig
/// The storage holds the caller-owned output arrays for one changed-page/// capture. The value borrows both slices. The caller keeps their addresses and/// captured prefixes unchanged for as long as a snapshot can be used.pub const Storage = struct {    capacity: Capacity,    indices: []u16,    pages: []align(page_bytes) u8,    /// The function joins an index slice and a page slice that carry the same    /// number of slots. Every index slot has one aligned page behind it in the    /// page storage. More than 16,384 indices returns `DeltaCapacityExceeded`.    /// Any other page-storage length returns `DeltaStorageMismatch`.    pub fn init(        indices: []u16,        pages: []align(page_bytes) u8,    ) Error!Storage {        const capacity = try Capacity.derive(indices.len);        if (pages.len != capacity.page_storage_bytes) {            return error.DeltaStorageMismatch;        }        return .{            .capacity = capacity,            .indices = indices,            .pages = pages,        };    }};

Source: lib/machine/src/checkpoint/canon/digest.zig:13

zig
pub const page_count: usize = core.layout.ram_bytes / page_bytes;
Called byCallsNo direct callscheckpoint.hot.Storageinittest sourcelib.machine.src.checkpoint.hot.ownertest: dirty tracking capacity rejects...private sourcelib.machine.src.checkpoint.hot.ownervalidateStoragecheckpoint.hot.Capacityderive
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/machine/src/checkpoint/hot/owner.zig:13

zig
/// The error set combines the failures of a durable checkpoint with destination/// aliasing for a snapshot.pub const Error = checkpoint.DurableError || HotError;
Called byCallsNo direct callersprivate sourcelib.machine.src.checkpoint.hot.ownerbuffersOverlapcheckpoint.hot.Snapshotaliases
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callscheckpoint.hot.SnapshotmaterializeForRestorecheckpoint.hot.SnapshotdirtyPageCount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallscheckpoint.hot.Snapshotrootprivate sourcelib.machine.src.checkpoint.hot.owner.Snapshotinspectcheckpoint.hot.Snapshotidentity
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerscheckpoint.hot.SnapshotdirtyPageCountprivate sourcelib.machine.src.checkpoint.hot.owner.Snapshotinspectprivate sourcelib.machine.src.checkpoint.hot.ownervalidateDestinationAgainstcheckpoint.hot.SnapshotmaterializeForRestore
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.machine.src.checkpoint.hot.owner.Snapshotinspectprivate sourcelib.machine.src.checkpoint.hot.ownervalidateDestinationAgainstcheckpoint.hot.SnapshotprepareForRestore
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callerscheckpoint.hot.Snapshotidentitycheckpoint.hot.Snapshotroot
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerscheckpoint.hot.Capacityderivecheckpoint.hot.Storageinit
Static calls · unresolved targets: 1 · external targets: 0.

Source: lib/machine/src/checkpoint/hot/owner.zig:233

zig
/// The function captures ordered changed pages from live memory against a/// durable parent. The material must share the parent's profile fingerprint,/// immutable image descriptor, and execution fingerprint. The supplied storage/// bounds the captured page count, and exceeding it returns/// `DeltaCapacityExceeded`. Failures before the identity is built leave both/// arrays unchanged, and rejection of the identity can leave both arrays/// changed. On success the returned snapshot holds borrowed references to the/// parent and to both output arrays.pub fn capture(    parent: *const checkpoint.Checkpoint,    material: checkpoint.Material,    current: []align(page_bytes) const u8,    storage: Storage,) Error!Snapshot {    const parent_contents = try checkpoint.inspect(parent);    try checkpoint.validateParent(material, parent_contents.material);    try validateStorage(storage);    try validateStorageAliases(parent, storage);    const delta = try checkpoint.captureDelta(        parent.ram,        current,        material.immutable_image,        storage.indices,        storage.pages,    );    const count: usize = delta.page_count;    const identity_value = try checkpoint.identify(material, delta.memory);    return .{        .parent = parent,        .identity_value = identity_value,        .memory = delta.memory,        .material = material,        .indices = storage.indices[0..count],        .pages = storage.pages[0 .. count * page_bytes],    };}
Called byCallsNo direct callersprivate sourcelib.machine.src.checkpoint.hot.ownervalidateStorageprivate sourcelib.machine.src.checkpoint.hot.ownervalidateStorageAliasescheckpoint.hotcapture
Static calls · unresolved targets: 1 · external targets: 4.

Source: lib/machine/src/checkpoint/hot/owner.zig:45

zig
pub const maximum_capacity = Capacity.derive(page_count) catch unreachable;

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

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

Source: lib/machine/src/checkpoint/root.zig:90

zig
pub const hot = @import("hot/root.zig");

Audit

Definitions18
Public names20
Members14
Version26.7.0
Revisiondaab053ee433