Struct Scheduler

Source
pub struct Scheduler<DL>
where DL: CellDataProvider,
{
Show 13 fields pub sg_data: SgData<DL>, pub debug_context: DebugContext, pub total_cycles: Arc<AtomicU64>, pub iteration_cycles: Cycle, pub next_vm_id: u64, pub next_fd_slot: u64, pub states: BTreeMap<u64, VmState>, pub fds: BTreeMap<Fd, u64>, pub inherited_fd: BTreeMap<u64, Vec<Fd>>, pub instantiated: BTreeMap<u64, (VmContext<DL>, AsmMachine)>, pub suspended: BTreeMap<u64, Snapshot2<DataPieceId>>, pub terminated_vms: BTreeMap<u64, i8>, pub message_box: Arc<Mutex<Vec<Message>>>,
}
Expand description

A single Scheduler instance is used to verify a single script within a CKB transaction.

A scheduler holds & manipulates a core, the scheduler also holds all CKB-VM machines, each CKB-VM machine also gets a mutable reference of the core for IO operations.

Fields§

§sg_data: SgData<DL>

Immutable context data for current running transaction & script.

§debug_context: DebugContext

Mutable context data used by current scheduler

§total_cycles: Arc<AtomicU64>

Total cycles. When a scheduler executes, there are 3 variables that might all contain charged cycles: +total_cycles+, +iteration_cycles+ and +machine.cycles()+ from the current executing virtual machine. At any given time, the sum of all 3 variables here, represent the total consumed cycles by the current scheduler. But there are also exceptions: at certain period of time, the cycles stored in machine.cycles() are moved over to +iteration_cycles+, the cycles stored in +iteration_cycles+ would also be moved over to +total_cycles+:

  • The current running virtual machine would contain consumed cycles in its own machine.cycles() structure.
  • +iteration_cycles+ holds the current consumed cycles each time we executed a virtual machine(also named an iteration). It will always be zero before each iteration(i.e., before each VM starts execution). When a virtual machine finishes execution, the cycles stored in machine.cycles() will be moved over to +iteration_cycles+. machine.cycles() will then be reset to zero.
  • Processing messages in the message box would alao charge cycles for operations, such as suspending/resuming VMs, transferring data etc. Those cycles were added to +iteration_cycles+ directly. When all postprocessing work is completed, the cycles consumed in +iteration_cycles+ will then be moved to +total_cycles+. +iteration_cycles+ will then be reset to zero.

One can consider that +total_cycles+ contains the total cycles consumed in current scheduler, when the scheduler is not busy executing.

§iteration_cycles: Cycle

Iteration cycles, see +total_cycles+ on its usage

§next_vm_id: u64

Next vm id used by spawn.

§next_fd_slot: u64

Next fd used by pipe.

§states: BTreeMap<u64, VmState>

Used to store VM state.

§fds: BTreeMap<Fd, u64>

Used to confirm the owner of fd.

§inherited_fd: BTreeMap<u64, Vec<Fd>>

Verify the VM’s inherited fd list.

§instantiated: BTreeMap<u64, (VmContext<DL>, AsmMachine)>

Instantiated vms.

§suspended: BTreeMap<u64, Snapshot2<DataPieceId>>

Suspended vms.

§terminated_vms: BTreeMap<u64, i8>

Terminated vms.

§message_box: Arc<Mutex<Vec<Message>>>

MessageBox is expected to be empty before returning from run function, there is no need to persist messages.

Implementations§

Source§

impl<DL> Scheduler<DL>

Source

pub fn new(sg_data: SgData<DL>, debug_context: DebugContext) -> Self

Create a new scheduler from empty state

Source

pub fn consumed_cycles(&self) -> Cycle

Return total cycles.

Source

pub fn consume_cycles(&mut self, cycles: Cycle) -> Result<(), Error>

Add cycles to total cycles.

Source

pub fn resume( sg_data: SgData<DL>, debug_context: DebugContext, full: FullSuspendedState, ) -> Self

Resume a previously suspended scheduler state

Source

pub fn suspend(self) -> Result<FullSuspendedState, Error>

Suspend current scheduler into a serializable full state

Source

pub fn run(&mut self, mode: RunMode) -> Result<(i8, Cycle), Error>

This is the only entrypoint for running the scheduler, both newly created instance and resumed instance are supported. It accepts 2 run mode, one can either limit the cycles to execute, or use a pause signal to trigger termination.

Only when the execution terminates without VM errors, will this function return an exit code(could still be non-zero) and total consumed cycles.

Err would be returned in the following cases:

  • Cycle limit reached, the returned error would be ckb_vm::Error::CyclesExceeded,
  • Pause trigger, the returned error would be ckb_vm::Error::Pause,
  • Other terminating errors
Source

pub fn iterate_prepare_machine( &mut self, ) -> Result<(u64, &mut AsmMachine), Error>

Returns the machine that needs to be executed in the current iterate.

Source

pub fn iterate_process_results( &mut self, vm_id_to_run: u64, result: Result<i8, Error>, ) -> Result<(), Error>

Process machine execution results in the current iterate.

Source

pub fn boot_vm( &mut self, location: &DataLocation, args: VmArgs, ) -> Result<u64, Error>

Boot a vm by given program and args.

Auto Trait Implementations§

§

impl<DL> Freeze for Scheduler<DL>

§

impl<DL> !RefUnwindSafe for Scheduler<DL>

§

impl<DL> Send for Scheduler<DL>
where DL: Sync + Send,

§

impl<DL> Sync for Scheduler<DL>
where DL: Sync + Send,

§

impl<DL> Unpin for Scheduler<DL>

§

impl<DL> !UnwindSafe for Scheduler<DL>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Cast to trait Any
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V