Simple interface for some VM lifecycle hooks.

This commit is contained in:
Florian Nücke
2020-12-15 04:26:30 +01:00
parent 61f02834f1
commit 0c8fa36de9
3 changed files with 50 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
package li.cil.oc2.api.bus.device.vm;
public interface VMLifecycleEventListener extends VMDevice {
void handleLifecycleEvent(VMLifecycleEventType event);
}

View File

@@ -0,0 +1,26 @@
package li.cil.oc2.api.bus.device.vm;
public enum VMLifecycleEventType {
/**
* Reported when the VM resumes running.
* <p>
* Fired after all devices reported success from {@link VMDevice#load(VMContext)}.
* <p>
* Fired on initial boot-up as well as when the VM resumes after being restored
* from a saved state. It is intended for awaiting asynchronous load operations.
*/
RESUME_RUNNING,
/**
* Reported exactly once, when the VM first starts running.
* <p>
* Fired after all devices reported success from {@link VMDevice#load(VMContext)}.
* <p>
* If a running VM is restored from a saved state, this event will not be fired. It is
* intended for initializing the VM state on boot, e.g. by loading initial executable
* code into memory.
* <p>
* <em>This is invoked from the worker thread running the VM.</em>
*/
INITIALIZE,
}

View File

@@ -4,13 +4,12 @@ import li.cil.ceres.api.Serialized;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
import li.cil.oc2.api.bus.device.vm.VMLifecycleEventListener;
import li.cil.oc2.api.bus.device.vm.VMLifecycleEventType;
import li.cil.sedna.api.Board;
import li.cil.sedna.riscv.device.R5PlatformLevelInterruptController;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Set;
import java.util.*;
public final class VirtualMachineDeviceBusAdapter {
private final Board board;
@@ -19,6 +18,8 @@ public final class VirtualMachineDeviceBusAdapter {
private final HashMap<VMDevice, ManagedVMContext> deviceContexts = new HashMap<>();
private final ArrayList<VMDevice> incompleteLoads = new ArrayList<>();
private final HashSet<VMLifecycleEventListener> lifecycleEventListeners = new HashSet<>();
///////////////////////////////////////////////////////////////////
// This is a superset of allocatedInterrupts. We use this so that after loading we
@@ -86,6 +87,12 @@ public final class VirtualMachineDeviceBusAdapter {
incompleteLoads.addAll(deviceContexts.keySet());
}
public void fireLifecycleEvent(final VMLifecycleEventType event) {
for (final VMLifecycleEventListener tickListener : lifecycleEventListeners) {
tickListener.handleLifecycleEvent(event);
}
}
public void addDevices(final Set<Device> devices) {
for (final Device device : devices) {
if (device instanceof VMDevice) {
@@ -97,6 +104,10 @@ public final class VirtualMachineDeviceBusAdapter {
}
incompleteLoads.add(vmDevice);
if (vmDevice instanceof VMLifecycleEventListener) {
lifecycleEventListeners.add((VMLifecycleEventListener) vmDevice);
}
}
}
}
@@ -113,6 +124,10 @@ public final class VirtualMachineDeviceBusAdapter {
incompleteLoads.remove(vmDevice);
if (vmDevice instanceof VMLifecycleEventListener) {
lifecycleEventListeners.remove(vmDevice);
}
vmDevice.unload();
}
}