mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-24 13:05:51 +00:00
CPU execution time costs energy #16
This commit is contained in:
parent
8701007ad9
commit
c703dec3cf
@ -29,6 +29,8 @@ public class GameServer implements Runnable {
|
||||
|
||||
private SocketServer socketServer;
|
||||
|
||||
private int maxExecutionTime;
|
||||
|
||||
public GameServer() {
|
||||
|
||||
this.config = new ServerConfiguration(new File("config.properties"));
|
||||
@ -36,6 +38,8 @@ public class GameServer implements Runnable {
|
||||
gameUniverse = new GameUniverse(config);
|
||||
pluginManager = new PluginManager();
|
||||
|
||||
maxExecutionTime = config.getInt("user_timeout");
|
||||
|
||||
//Load all plugins in plugins folder, if it doesn't exist, create it
|
||||
File pluginDir = new File("plugins/");
|
||||
File[] pluginDirListing = pluginDir.listFiles();
|
||||
@ -109,8 +113,13 @@ public class GameServer implements Runnable {
|
||||
|
||||
if(user.getCpu() != null){
|
||||
try {
|
||||
|
||||
int timeout = Math.min(user.getControlledUnit().getEnergy(), maxExecutionTime);
|
||||
|
||||
user.getCpu().reset();
|
||||
user.getCpu().execute();
|
||||
int cost = user.getCpu().execute(timeout);
|
||||
user.getControlledUnit().spendEnergy(cost);
|
||||
|
||||
} catch (Exception e) {
|
||||
LogManager.LOGGER.severe("Error executing " + user.getUsername() + "'s code");
|
||||
e.printStackTrace();
|
||||
|
@ -253,6 +253,8 @@ public class Assembler {
|
||||
|
||||
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
||||
|
||||
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
||||
|
||||
result.defineSegment(Segment.DATA, currentLine, currentOffset);
|
||||
throw new PseudoInstructionException(currentLine);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.simon987.server.assembly;
|
||||
import net.simon987.server.ServerConfiguration;
|
||||
import net.simon987.server.assembly.exception.AssemblyException;
|
||||
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -29,7 +30,7 @@ public class AssemblyResult {
|
||||
/**
|
||||
* Offset of the code segment
|
||||
*/
|
||||
private int codeSegmentOffset;
|
||||
public int codeSegmentOffset;
|
||||
/**
|
||||
* Line of the code segment definition (for editor icons)
|
||||
*/
|
||||
@ -77,6 +78,10 @@ public class AssemblyResult {
|
||||
if (!codeSegmentSet) {
|
||||
codeSegmentOffset = origin + currentOffset;
|
||||
codeSegmentLine = currentLine;
|
||||
|
||||
LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSegmentOffset);
|
||||
|
||||
|
||||
codeSegmentSet = true;
|
||||
} else {
|
||||
throw new DuplicateSegmentException(currentLine);
|
||||
@ -87,6 +92,9 @@ public class AssemblyResult {
|
||||
if (!dataSegmentSet) {
|
||||
dataSegmentOffset = origin + currentOffset;
|
||||
dataSegmentLine = currentLine;
|
||||
|
||||
LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSegmentOffset);
|
||||
|
||||
dataSegmentSet = true;
|
||||
} else {
|
||||
throw new DuplicateSegmentException(currentLine);
|
||||
|
@ -60,10 +60,11 @@ public class CPU implements JSONSerialisable{
|
||||
|
||||
private ServerConfiguration config;
|
||||
|
||||
private long timeout;
|
||||
|
||||
private int registerSetSize;
|
||||
|
||||
private static final char EXECUTION_COST_ADDR = 0x0300;
|
||||
private static final char EXECUTED_INS_ADDR = 0x0301;
|
||||
|
||||
/**
|
||||
* Creates a new CPU
|
||||
*/
|
||||
@ -74,8 +75,6 @@ public class CPU implements JSONSerialisable{
|
||||
attachedHardware = new HashMap<>();
|
||||
codeSegmentOffset = config.getInt("org_offset");
|
||||
|
||||
timeout = config.getInt("user_timeout");
|
||||
|
||||
instructionSet.add(new JmpInstruction(this));
|
||||
instructionSet.add(new JnzInstruction(this));
|
||||
instructionSet.add(new JzInstruction(this));
|
||||
@ -116,7 +115,7 @@ public class CPU implements JSONSerialisable{
|
||||
ip = codeSegmentOffset;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
public int execute(int timeout) {
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
int counter = 0;
|
||||
@ -128,10 +127,16 @@ public class CPU implements JSONSerialisable{
|
||||
while (!status.isBreakFlag()) {
|
||||
counter++;
|
||||
|
||||
if(counter % 1000 == 0){
|
||||
if (counter % 10000 == 0) {
|
||||
if (System.currentTimeMillis() >= (startTime + timeout)) {
|
||||
LogManager.LOGGER.fine("CPU Timeout " + this + " after " + counter + "instructions (" + timeout + "ms): " + (double) counter / ((double) timeout / 1000) / 1000000 + "MHz");
|
||||
return;
|
||||
|
||||
//Write execution cost and instruction count to memory
|
||||
memory.set(EXECUTION_COST_ADDR, timeout);
|
||||
memory.set(EXECUTED_INS_ADDR, Util.getHigherWord(counter));
|
||||
memory.set(EXECUTED_INS_ADDR, Util.getLowerWord(counter));
|
||||
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,8 +156,17 @@ public class CPU implements JSONSerialisable{
|
||||
executeInstruction(instruction, source, destination);
|
||||
// LogManager.LOGGER.info(instruction.getMnemonic());
|
||||
}
|
||||
double elapsed = (System.currentTimeMillis() - startTime);
|
||||
int elapsed = (int) (System.currentTimeMillis() - startTime);
|
||||
|
||||
LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
|
||||
|
||||
|
||||
//Write execution cost and instruction count to memory
|
||||
memory.set(EXECUTION_COST_ADDR, elapsed);
|
||||
memory.set(EXECUTED_INS_ADDR, Util.getHigherWord(counter));
|
||||
memory.set(EXECUTED_INS_ADDR, Util.getLowerWord(counter));
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
public void executeInstruction(Instruction instruction, int source, int destination) {
|
||||
|
@ -42,14 +42,14 @@ public class Memory implements Target, JSONSerialisable {
|
||||
*/
|
||||
@Override
|
||||
public int get(int address) {
|
||||
address = (char)address * 2; //Because our Memory is only divisible by 16bits
|
||||
address = address * 2; //Because our Memory is only divisible by 16bits
|
||||
|
||||
if (address < 0 || address + 2 > bytes.length) {
|
||||
if (address + 2 > bytes.length) {
|
||||
LogManager.LOGGER.info("DEBUG: Trying to get memory out of bounds " + address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (((bytes[address] & 0xFF) << 8) | (bytes[address + 1] & 0xFF));
|
||||
return ((bytes[address] & 0xFF) << 8) | (bytes[address + 1] & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ public class Memory implements Target, JSONSerialisable {
|
||||
offset = (char)offset * 2;
|
||||
|
||||
|
||||
if (offset + count > this.bytes.length || count < 0 || offset < 0 || srcOffset >= bytes.length) {
|
||||
if (offset + count > this.bytes.length || srcOffset >= bytes.length || count < 0 || offset < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -80,12 +80,12 @@ public class Memory implements Target, JSONSerialisable {
|
||||
address = (char)address * 2;
|
||||
|
||||
|
||||
if (address < 0 || address + 2 > bytes.length) {
|
||||
if (address + 2 > bytes.length) {
|
||||
LogManager.LOGGER.info("DEBUG: Trying to set memory out of bounds: " + address);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes[address] = (byte) ((value >> 8) & 0xFF);
|
||||
bytes[address] = (byte) ((value >> 8));
|
||||
bytes[address + 1] = (byte) (value & 0xFF);
|
||||
}
|
||||
|
||||
|
@ -17,4 +17,8 @@ public interface ControllableUnit {
|
||||
|
||||
Memory getFloppyData();
|
||||
|
||||
boolean spendEnergy(int energy);
|
||||
|
||||
int getEnergy();
|
||||
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ public class GameUniverse implements JSONSerialisable{
|
||||
|
||||
//Write assembled code to mem
|
||||
user.getCpu().getMemory().write((short) ar.origin, ar.bytes, 0, ar.bytes.length);
|
||||
user.getCpu().setCodeSegmentOffset(ar.origin);
|
||||
user.getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
||||
|
||||
//Init
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class CodeUploadHandler implements MessageHandler {
|
||||
|
||||
//Write assembled code to mem
|
||||
user.getUser().getCpu().getMemory().write((char) ar.origin, ar.bytes, 0, ar.bytes.length);
|
||||
user.getUser().getCpu().setCodeSegmentOffset(ar.origin);
|
||||
user.getUser().getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
||||
|
||||
JSONObject response = new JSONObject();
|
||||
response.put("t", "codeResponse");
|
||||
|
@ -60,4 +60,6 @@ wg_minCopperCount=0
|
||||
wg_maxCopperCount=2
|
||||
# ----------------------------------------------
|
||||
# Maximum execution time of user code in ms
|
||||
user_timeout=40
|
||||
user_timeout=500
|
||||
# Free CPU execution time in ms
|
||||
user_free_execution_time=2
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user