Simple interface for some VM lifecycle hooks.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package li.cil.oc2.api.bus.device.vm;
|
||||
|
||||
public interface VMLifecycleEventListener extends VMDevice {
|
||||
void handleLifecycleEvent(VMLifecycleEventType event);
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user