pub enum CloneMode {
Fork,
Thread,
}Expand description
How WorkloadHandle::spawn creates worker tasks.
Fork is the default — the existing fork(2) path with
separate address space, separate thread group, and waitpid
reaping. Thread switches to std::thread::spawn for workers
that share the test runner’s tgid.
§WorkType × CloneMode compatibility
Most WorkType variants compose with both clone modes. The
only exception is surfaced at spawn time by
WorkloadHandle::spawn:
| WorkType | Fork | Thread |
|---|---|---|
| All variants (default) | OK | OK |
WorkType::ForkExit | OK | reject |
ForkExit + Thread is rejected because the worker body calls
libc::fork() from inside a thread of the multi-threaded harness:
the fork duplicates only the calling thread, so any lock another
thread holds at fork time stays locked forever in the child. The
child only _exits here — and fork() omits CLONE_THREAD, so the
child is its own singleton tgid; its _exit invokes exit_group(2),
but that tgid has no sibling threads to tear down, so it ends only
the child — but the fork/exit lifecycle is faithfully exercised only
when each worker is its own process. Use CloneMode::Fork for
WorkType::ForkExit.
Other Thread-mode interactions worth knowing:
WorkType::NiceSweep:setpriority(PRIO_PROCESS, 0, …)targets the calling task only (kernel/sys.c::sys_setprioritycase PRIO_PROCESS: if (who == 0) p = current), so each sibling thread independently sweeps its own nice. Allowed.WorkType::AffinityChurn:sched_setaffinity(0, …)addresses the calling thread by kernel rule (kernel/sched/syscalls.c::sched_setaffinity). Allowed; no cross-thread interference.WorkType::PolicyChurn:sched_setscheduler(0, …)is also per-task. Allowed.WorkType::AsymmetricWakerwith an RT class: legal but the harness still runs as its original (likely SCHED_NORMAL) policy; only the worker thread is RT.
Variants§
Fork
Plain fork(2): separate address space, separate thread
group (p->tgid = p->pid), reaped via waitpid. The default
— preserves existing WorkloadHandle::spawn behavior.
Thread
Same thread group as the spawning process. Implementation
uses std::thread::spawn; the Rust thread runtime owns
all clone-flag selection internally. Reaped via
std::thread::JoinHandle. Workers share tgid,
signal-handler table, and address space with the parent —
observers like task_struct->group_leader, tgid,
real_parent all match the parent’s.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for CloneMode
impl<'de> Deserialize<'de> for CloneMode
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Copy for CloneMode
impl Eq for CloneMode
impl StructuralPartialEq for CloneMode
Auto Trait Implementations§
impl Freeze for CloneMode
impl RefUnwindSafe for CloneMode
impl Send for CloneMode
impl Sync for CloneMode
impl Unpin for CloneMode
impl UnwindSafe for CloneMode
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<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<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
§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>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more