// PART OF THE MACHINE SIMULATION. DO NOT CHANGE.
package nachos.ag;
import nachos.machine.*;
import nachos.security.*;
import nachos.threads.*;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* The default autograder. Loads the kernel, and then tests it using
* <tt>Kernel.selfTest()</tt>.
*/
public class AutoGrader
{
/**
* Allocate a new autograder.
*/
public AutoGrader ()
{
}
/**
* Start this autograder. Extract the <tt>-#</tt> arguments, call
* <tt>init()</tt>, load and initialize the kernel, and call <tt>run()</tt>.
*
* @param privilege
* encapsulates privileged access to the Nachos machine.
*/
public void start (Privilege privilege)
{
Lib.assertTrue(this.privilege == null, "start() called multiple times");
this.privilege = privilege;
String[] args = Machine.getCommandLineArguments();
extractArguments(args);
System.out.print(" grader");
init();
System.out.print("\n");
kernel = (Kernel)Lib.constructObject(Config.getString("Kernel.kernel"));
kernel.initialize(args);
run();
}
private void extractArguments (String[] args)
{
String testArgsString = Config.getString("AutoGrader.testArgs");
if (testArgsString == null)
{
testArgsString = "";
}
for (int i = 0; i < args.length;)
{
String arg = args[i++];
if (arg.length() > 0 && arg.charAt(0) == '-')
{
if (arg.equals("-#"))
{
Lib.assertTrue(i < args.length, "-# switch missing argument");
testArgsString = args[i++];
}
}
}
StringTokenizer st = new StringTokenizer(testArgsString, ",\n\t\f\r");
while (st.hasMoreTokens())
{
StringTokenizer pair = new StringTokenizer(st.nextToken(), "=");
Lib.assertTrue(pair.hasMoreTokens(), "test argument missing key");
String key = pair.nextToken();
Lib.assertTrue(pair.hasMoreTokens(), "test argument missing value");
String value = pair.nextToken();
testArgs.put(key, value);
}
}
String getStringArgument (String key)
{
String value = (String)testArgs.get(key);
Lib.assertTrue(value != null, "getStringArgument(" + key
+ ") failed to find key");
return value;
}
int getIntegerArgument (String key)
{
try
{
return Integer.parseInt(getStringArgument(key));
}
catch (NumberFormatException e)
{
Lib.assertNotReached("getIntegerArgument(" + key + ") failed: "
+ "value is not an integer");
return 0;
}
}
boolean getBooleanArgument (String key)
{
String value = getStringArgument(key);
if (value.equals("1") || value.toLowerCase().equals("true"))
{
return true;
}
else if (value.equals("0") || value.toLowerCase().equals("false"))
{
return false;
}
else
{
Lib.assertNotReached("getBooleanArgument(" + key + ") failed: "
+ "value is not a boolean");
return false;
}
}
long getTime ()
{
return privilege.stats.totalTicks;
}
void targetLevel (int targetLevel)
{
this.targetLevel = targetLevel;
}
void level (int level)
{
this.level++;
Lib.assertTrue(level == this.level,
"level() advanced more than one step: test jumped ahead");
if (level == targetLevel)
done();
}
private int level = 0, targetLevel = 0;
void done ()
{
System.out.print("\nsuccess\n");
privilege.exit(162);
}
private Hashtable<String, String> testArgs = new Hashtable<String, String>();
void init ()
{
}
void run ()
{
kernel.selfTest();
kernel.run();
kernel.terminate();
}
Privilege privilege = null;
Kernel kernel;
/**
* Notify the autograder that the specified thread is the idle thread.
* <tt>KThread.createIdleThread()</tt> <i>must</i> call this method before
* forking the idle thread.
*
* @param idleThread
* the idle thread.
*/
public void setIdleThread (KThread idleThread)
{
}
/**
* Notify the autograder that the specified thread has moved to the ready
* state. <tt>KThread.ready()</tt> <i>must</i> call this method before
* returning.
*
* @param thread
* the thread that has been added to the ready set.
*/
public void readyThread (KThread thread)
{
}
/**
* Notify the autograder that the specified thread is now running.
* <tt>KThread.restoreState()</tt> <i>must</i> call this method before
* returning.
*
* @param thread
* the thread that is now running.
*/
public void runningThread (KThread thread)
{
privilege.tcb.associateThread(thread);
currentThread = thread;
}
/**
* Notify the autograder that the current thread has finished.
* <tt>KThread.finish()</tt> <i>must</i> call this method before putting the
* thread to sleep and scheduling its TCB to be destroyed.
*/
public void finishingCurrentThread ()
{
privilege.tcb.authorizeDestroy(currentThread);
}
/**
* Notify the autograder that a timer interrupt occurred and was handled by
* software if a timer interrupt handler was installed. Called by the hardware
* timer.
*
* @param privilege
* proves the authenticity of this call.
* @param time
* the actual time at which the timer interrupt was issued.
*/
public void timerInterrupt (Privilege privilege, long time)
{
Lib.assertTrue(privilege == this.privilege, "security violation");
}
/**
* Notify the autograder that a user program executed a syscall instruction.
*
* @param privilege
* proves the authenticity of this call.
* @return <tt>true</tt> if the kernel exception handler should be called.
*/
public boolean exceptionHandler (Privilege privilege)
{
Lib.assertTrue(privilege == this.privilege, "security violation");
return true;
}
/**
* Notify the autograder that <tt>Processor.run()</tt> was invoked. This can
* be used to simulate user programs.
*
* @param privilege
* proves the authenticity of this call.
*/
public void runProcessor (Privilege privilege)
{
Lib.assertTrue(privilege == this.privilege, "security violation");
}
/**
* Notify the autograder that a COFF loader is being constructed for the
* specified file. The autograder can use this to provide its own COFF loader,
* or return <tt>null</tt> to use the default loader.
*
* @param file
* the executable file being loaded.
* @return a loader to use in loading the file, or <tt>null</tt> to use the
* default.
*/
public Coff createLoader (OpenFile file)
{
return null;
}
/**
* Request permission to send a packet. The autograder can use this to drop
* packets very selectively.
*
* @param privilege
* proves the authenticity of this call.
* @return <tt>true</tt> if the packet should be sent.
*/
public boolean canSendPacket (Privilege privilege)
{
Lib.assertTrue(privilege == this.privilege, "security violation");
return true;
}
/**
* Request permission to receive a packet. The autograder can use this to drop
* packets very selectively.
*
* @param privilege
* proves the authenticity of this call.
* @return <tt>true</tt> if the packet should be delivered to the kernel.
*/
public boolean canReceivePacket (Privilege privilege)
{
Lib.assertTrue(privilege == this.privilege, "security violation");
return true;
}
boolean hasArgument (String key)
{
return testArgs.get(key) != null;
}
private KThread currentThread;
}