pub struct HappensBeforeProgram {
pub version: u32,
pub anchors: BTreeMap<String, Anchor>,
pub edges: Vec<HappensBeforeEdge>,
pub max_hold_ns: Option<u64>,
}Expand description
A validated, normalized happens-before program: anchors indexed by name plus the edge list, guaranteed acyclic with all references resolved.
Fields§
§version: u32The spec’s schema version.
anchors: BTreeMap<String, Anchor>Normalized anchors, keyed by event name.
edges: Vec<HappensBeforeEdge>The validated, acyclic edge list.
max_hold_ns: Option<u64>The hold budget in committed virtual nanoseconds: Some for a
version-2 spec (its max_hold_ns, or DEFAULT_MAX_HOLD_NS), None
for version 1, which has no budget.
Implementations§
Source§impl HappensBeforeProgram
impl HappensBeforeProgram
Sourcepub fn unresolved_locations(&self) -> impl Iterator<Item = &Anchor>
pub fn unresolved_locations(&self) -> impl Iterator<Item = &Anchor>
Anchors that still require debug-info resolution (an unresolved RIP from a
code location, i.e. a func/line that has not been turned into an
address yet).
Sourcepub fn may_have_syscall_count_anchor_at(
&self,
dettid: DetTid,
count: u64,
) -> bool
pub fn may_have_syscall_count_anchor_at( &self, dettid: DetTid, count: u64, ) -> bool
True when thread dettid must check in with the scheduler at its
syscall number count: some anchor sits at exactly
Position::SyscallCount(count) and names dettid, or names its
thread by spawn ordinal (which only the scheduler can resolve, so the
guest side must ask). For any other (thread, count) the scheduler’s
checkpoint finds no anchor and does nothing, so skipping it changes no
gate. It costs one scheduler round trip per anchor its thread reaches,
not one per syscall (https://github.com/rrnewton/hermit/issues/3877),
and threads a spec does not name keep their schedule: a count another
thread passes early (QEMU’s main loop makes about a million syscalls a
run) no longer adds a scheduler turn there.
Sourcepub fn has_syscall_occurrence_anchors(&self) -> bool
pub fn has_syscall_occurrence_anchors(&self) -> bool
True when the program has any enforced syscall-occurrence anchor
(Anchor::is_syscall_occurrence), so the guest must count its calls.
Sourcepub fn count_syscall_occurrences(
&self,
counters: &mut HbThreadCounters,
dettid: DetTid,
sysno: Sysno,
args: [usize; 2],
entry_count: u64,
) -> Vec<String>
pub fn count_syscall_occurrences( &self, counters: &mut HbThreadCounters, dettid: DetTid, sysno: Sysno, args: [usize; 2], entry_count: u64, ) -> Vec<String>
Count one syscall entry of thread dettid (sysno, first two
arguments args, the thread’s entry_countth syscall) in that
thread’s counters, and return the names of the syscall-occurrence
anchors this entry fires.
counters belongs to one thread and is kept with its other per-thread
counts (the syscall count that count anchors use), so it starts empty
for every new thread. Per entry, in this order:
- Every distinct occurrence key (syscall, fd, futex operation) an anchor names that the entry matches is incremented once; an entry that matches both an fd-specific and an fd-agnostic anchor counts toward each.
- Each relative anchor whose base this entry reaches gets its origin:
its own key’s count after step 1, so the base entry is never counted
in its window. A count base is reached when
entry_countequals its count, whether or not the entry matches any key. - An absolute anchor fires when its key’s count equals
nth; a relative anchor fires when its count minus its origin equalsnth.
An entry is counted exactly once, when the thread enters the syscall,
so a thread held at an anchor and re-admitted does not count again. The
result names anchors on dettid or on a spawn ordinal; the scheduler
resolves spawn ordinals and fires only the anchors on this thread.
Sourcepub fn is_version_2(&self) -> bool
pub fn is_version_2(&self) -> bool
True for a version-2 program, which carries a hold budget and needs an effective preemption timer to charge it.
Sourcepub fn relative_anchors(&self) -> impl Iterator<Item = (&Anchor, &Anchor)>
pub fn relative_anchors(&self) -> impl Iterator<Item = (&Anchor, &Anchor)>
The relative anchors and their bases, in name order.
Sourcepub fn unenforced_positions(&self) -> impl Iterator<Item = &Anchor>
pub fn unenforced_positions(&self) -> impl Iterator<Item = &Anchor>
Anchors whose position kind the current scheduler does not yet enforce:
everything other than Position::SyscallCount and the syscall
occurrence anchors (Anchor::is_syscall_occurrence). Reported so a run
does not silently ignore an authored ordering constraint it cannot honor.
Trait Implementations§
Source§impl Clone for HappensBeforeProgram
impl Clone for HappensBeforeProgram
Source§fn clone(&self) -> HappensBeforeProgram
fn clone(&self) -> HappensBeforeProgram
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for HappensBeforeProgram
impl Debug for HappensBeforeProgram
impl Eq for HappensBeforeProgram
Source§impl PartialEq for HappensBeforeProgram
impl PartialEq for HappensBeforeProgram
impl StructuralPartialEq for HappensBeforeProgram
Auto Trait Implementations§
impl Freeze for HappensBeforeProgram
impl RefUnwindSafe for HappensBeforeProgram
impl Send for HappensBeforeProgram
impl Sync for HappensBeforeProgram
impl Unpin for HappensBeforeProgram
impl UnsafeUnpin for HappensBeforeProgram
impl UnwindSafe for HappensBeforeProgram
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.