default RunResult run(Trace trace, TraceThread eventThread, PcodeMachine<?> machine,
			TaskMonitor monitor) {
		TraceThreadManager tm = trace.getThreadManager();
		TraceSchedule completedSteps = TraceSchedule.snap(0);
		PcodeThread<?> emuThread = null;
		int completedTicks = 0;
		try {
			while (true) {
				TickStep slice = nextSlice(trace);
				eventThread = slice.getThread(tm, eventThread);
				emuThread = machine.getThread(eventThread.getPath(), true);
				long ticksLeft = slice.tickCount;
				if (ticksLeft > 0 && emuThread.getFrame() != null) {
					monitor.checkCancelled();
					emuThread.finishInstruction();
					ticksLeft--;
					completedTicks++;
				}
				while (ticksLeft > 0) {
					monitor.checkCancelled();
					emuThread.stepInstruction();
					ticksLeft--;
					completedTicks++;
				}
				completedSteps = completedSteps.steppedForward(eventThread, completedTicks);
				completedTicks = 0;
			}
		}
		catch (PcodeExecutionException e) {
			completedSteps = completedSteps.steppedForward(eventThread, completedTicks);
			PcodeFrame frame = emuThread.getFrame();
			if (frame == null) {
				return new RecordRunResult(completedSteps.assumeRecorded(), e);
			}
			// Rewind one so stepping retries the op causing the error
			frame.stepBack();
			int count = frame.resetCount();
			if (count == 0) {
				// If we've decoded, but could not execute the first op, just drop the p-code steps
				emuThread.dropInstruction();
				return new RecordRunResult(completedSteps, e);
			}
			// The +1 accounts for the decode step
			return new RecordRunResult(
				completedSteps.steppedPcodeForward(eventThread, count + 1).assumeRecorded(), e);
		}
		catch (CancelledException e) {
			return new RecordRunResult(
				completedSteps.steppedForward(eventThread, completedTicks).assumeRecorded(), e);
		}
	}
Run a machine according to the given schedule until it is interrupted

<p>
This method will drop p-code steps from injections, including those from execution
breakpoints. The goal is to ensure that the returned schedule can be used to recover the same
state on a machine without injections. Unfortunately, injections which modify the machine
state, other than unique variables, will defeat that goal.

@param trace the trace whose threads to schedule
@param eventThread the first thread to schedule if the scheduler doesn't specify
@param machine the machine to run
@param monitor a monitor for cancellation
@return the result of execution
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Scheduler.java