Compare commits
5 Commits
865eed3648
...
36a4dab13a
Author | SHA1 | Date |
---|---|---|
ginger88895 | 36a4dab13a | |
ginger88895 | a114fc9a74 | |
ginger88895 | b0db63c1d4 | |
ginger88895 | ae15de9334 | |
ginger88895 | 896a089252 |
|
@ -0,0 +1,13 @@
|
|||
nachos 5.0j initializing... config interrupt timer processor console user-check grader
|
||||
*** thread 0 looped 0 times
|
||||
*** thread 0 looped 1 times
|
||||
*** thread 1 looped 0 times
|
||||
*** thread 0 looped 2 times
|
||||
*** thread 1 looped 1 times
|
||||
*** thread 0 looped 3 times
|
||||
*** thread 1 looped 2 times
|
||||
*** thread 0 looped 4 times
|
||||
*** thread 1 looped 3 times
|
||||
*** thread 1 looped 4 times
|
||||
Testing the console device. Typed characters
|
||||
will be echoed until q is typed.
|
|
@ -8,7 +8,7 @@ Processor.usingTLB = false
|
|||
Processor.numPhysPages = 64
|
||||
ElevatorBank.allowElevatorGUI = false
|
||||
NachosSecurityManager.fullySecure = false
|
||||
ThreadedKernel.scheduler = nachos.threads.RoundRobinScheduler #nachos.threads.LotteryScheduler
|
||||
ThreadedKernel.scheduler = nachos.threads.LotteryScheduler
|
||||
Kernel.shellProgram = halt.coff #sh.coff
|
||||
Kernel.processClassName = nachos.userprog.UserProcess
|
||||
Kernel.kernel = nachos.userprog.UserKernel
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -9,6 +9,7 @@
|
|||
# setenv ARCHDIR ../mips-x86.win32-xgcc
|
||||
|
||||
# you need to point to the right executables
|
||||
ARCHDIR = ../../mips-x86.linux-xgcc
|
||||
GCCDIR = $(ARCHDIR)/mips-
|
||||
|
||||
ASFLAGS = -mips1
|
||||
|
@ -32,8 +33,7 @@ STDLIB_O = start.o stdio.o stdlib.o
|
|||
LIB = assert atoi printf readline stdio strncmp strcat strcmp strcpy strlen memcpy memset
|
||||
NLIB = libnachos.a
|
||||
|
||||
#TARGETS = halt sh matmult sort echo cat cp mv rm #chat chatserver
|
||||
TARGETS = mytest1
|
||||
TARGETS = halt sh matmult sort echo cat cp mv rm mytest1 mytest2a mytest2b mytest2c mytest2d mytest3 mytest4 #chat chatserver
|
||||
|
||||
.SECONDARY: $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/libnachos.a
BIN
test/libnachos.a
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,14 +2,23 @@
|
|||
#include "stdio.h"
|
||||
|
||||
char buf[100];
|
||||
char* tt[]={"hello!","welcome!"};
|
||||
int main()
|
||||
{
|
||||
printf("pid=%d\n",exec("mytest2a.coff",0,0));
|
||||
printf("pid=%d\n",exec("mytest2b.coff",0,0));
|
||||
printf("pid=%d\n",exec("mytest2d.coff",2,tt));
|
||||
//exec("mytest2c.coff",0,0);
|
||||
while(1);
|
||||
return 0;
|
||||
/*
|
||||
int ff=creat("data");
|
||||
close(ff);
|
||||
write(1,"10 200\n",strlen("10 200\n"));
|
||||
printf("%d\n",write(ff,"10 200\n",10));
|
||||
halt();
|
||||
return 0;
|
||||
*/
|
||||
|
||||
/*
|
||||
int a=0,b=0,i=0;
|
||||
|
@ -33,7 +42,7 @@ int main()
|
|||
}
|
||||
printf("%d+%d=%d\n",a,b,a+b);
|
||||
halt();
|
||||
*/
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
BIN
test/mytest1.o
BIN
test/mytest1.o
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
int xid=5;
|
||||
int main()
|
||||
{
|
||||
int id=5;
|
||||
while(1);
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
int xid=7;
|
||||
int main()
|
||||
{
|
||||
int id=7;
|
||||
while(1);
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
char buf[100];
|
||||
int main()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
int f=open("pool");
|
||||
read(f,buf,100);
|
||||
printf("%s\n",buf);
|
||||
close(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
char buf[100];
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
//printf("%s\n",argv[0]);
|
||||
//printf("%s\n",argv[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,75 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
char buf[100];
|
||||
char* tt[]={"hello!","welcome!"};
|
||||
int main()
|
||||
{
|
||||
int cid,tmp;
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
cid=exec("mytest4.coff",0,0);
|
||||
printf("pid=%d\n",cid);
|
||||
join(cid,&tmp);
|
||||
halt();
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int i=0;
|
||||
for(i=0;i<10000;i++)
|
||||
{
|
||||
if(i%10000==0)
|
||||
printf("i=%d\n",i);
|
||||
}
|
||||
return 12;
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4,7 +4,9 @@ import nachos.machine.*;
|
|||
|
||||
import java.util.TreeSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* A scheduler that chooses threads using a lottery.
|
||||
|
@ -30,8 +32,60 @@ public class LotteryScheduler extends PriorityScheduler {
|
|||
/**
|
||||
* Allocate a new lottery scheduler.
|
||||
*/
|
||||
public LotteryScheduler() {
|
||||
public LotteryScheduler()
|
||||
{
|
||||
num_tickets=0;
|
||||
rng=new Random();
|
||||
thread_original_tickets=new HashMap<KThread,Integer>();
|
||||
thread_effective_tickets=new HashMap<KThread,Integer>();
|
||||
upstream=new HashMap<KThread,HashMap<KThread,Integer>>();
|
||||
}
|
||||
|
||||
public int getPriority(KThread thread)
|
||||
{
|
||||
Lib.assertTrue(Machine.interrupt().disabled());
|
||||
init_thread_tickets(thread);
|
||||
return thread_original_tickets.get(thread);
|
||||
}
|
||||
|
||||
public int getEffectivePriority(KThread thread)
|
||||
{
|
||||
Lib.assertTrue(Machine.interrupt().disabled());
|
||||
init_thread_tickets(thread);
|
||||
return thread_effective_tickets.get(thread);
|
||||
}
|
||||
|
||||
public void setPriority(KThread thread,int priority)
|
||||
{
|
||||
Lib.assertTrue(Machine.interrupt().disabled());
|
||||
Lib.assertTrue(priority>=min_tickets&&priority<=max_tickets);
|
||||
init_thread_tickets(thread);
|
||||
update(thread,priority-thread_original_tickets.get(thread));
|
||||
}
|
||||
|
||||
public boolean increasePriority()
|
||||
{
|
||||
boolean intStatus = Machine.interrupt().disable();
|
||||
KThread thread = KThread.currentThread();
|
||||
int priority=getPriority(thread);
|
||||
if(priority==priorityMaximum)
|
||||
return false;
|
||||
update(thread,1);
|
||||
Machine.interrupt().restore(intStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean decreasePriority()
|
||||
{
|
||||
boolean intStatus = Machine.interrupt().disable();
|
||||
KThread thread = KThread.currentThread();
|
||||
int priority=getPriority(thread);
|
||||
if(priority==priorityMinimum)
|
||||
return false;
|
||||
update(thread,-1);
|
||||
Machine.interrupt().restore(intStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new lottery thread queue.
|
||||
|
@ -41,8 +95,116 @@ public class LotteryScheduler extends PriorityScheduler {
|
|||
* to the owning thread.
|
||||
* @return a new lottery thread queue.
|
||||
*/
|
||||
public ThreadQueue newThreadQueue(boolean transferPriority) {
|
||||
// implement me
|
||||
return null;
|
||||
public ThreadQueue newThreadQueue(boolean transferPriority)
|
||||
{
|
||||
return new lottery_queue(transferPriority);
|
||||
}
|
||||
|
||||
protected void init_thread_tickets(KThread x)
|
||||
{
|
||||
if(!thread_original_tickets.containsKey(x))
|
||||
{
|
||||
num_tickets+=1;
|
||||
thread_original_tickets.put(x,1);
|
||||
thread_effective_tickets.put(x,1);
|
||||
upstream.put(x,new HashMap<KThread,Integer>());
|
||||
}
|
||||
}
|
||||
|
||||
protected void update(KThread x,int amount)
|
||||
{
|
||||
//System.out.println("Update effective tickets by "+amount+": "+x);
|
||||
num_tickets+=amount;
|
||||
thread_effective_tickets.put(x,thread_effective_tickets.get(x)+amount);
|
||||
HashMap<KThread,Integer> tmp=upstream.get(x);
|
||||
for(KThread y:tmp.keySet())
|
||||
if(tmp.get(y)!=0)
|
||||
update(y,tmp.get(y)*amount);
|
||||
}
|
||||
|
||||
protected void add_upstream(KThread x,KThread y)
|
||||
{
|
||||
update(y,thread_effective_tickets.get(x));
|
||||
if(!upstream.get(x).containsKey(y))
|
||||
upstream.get(x).put(y,1);
|
||||
else
|
||||
upstream.get(x).put(y,upstream.get(x).get(y)+1);
|
||||
}
|
||||
|
||||
protected void remove_upstream(KThread x,KThread y)
|
||||
{
|
||||
update(y,-thread_effective_tickets.get(x));
|
||||
upstream.get(x).put(y,upstream.get(x).get(y)-1);
|
||||
}
|
||||
|
||||
protected class lottery_queue extends ThreadQueue
|
||||
{
|
||||
public lottery_queue(boolean transfer)
|
||||
{
|
||||
this.transfer=transfer;
|
||||
acquiring_process=null;
|
||||
waiting_queue=new HashSet<KThread>();
|
||||
}
|
||||
public void waitForAccess(KThread thread)
|
||||
{
|
||||
init_thread_tickets(thread);
|
||||
waiting_queue.add(thread);
|
||||
if(transfer&&acquiring_process!=null)
|
||||
add_upstream(thread,acquiring_process);
|
||||
}
|
||||
public void acquire(KThread thread)
|
||||
{
|
||||
init_thread_tickets(thread);
|
||||
acquiring_process=thread;
|
||||
if(transfer)
|
||||
for(KThread x:waiting_queue)
|
||||
add_upstream(x,thread);
|
||||
}
|
||||
public KThread nextThread()
|
||||
{
|
||||
if(waiting_queue.isEmpty())
|
||||
{
|
||||
acquiring_process=null;
|
||||
return null;
|
||||
}
|
||||
KThread result=null;
|
||||
int waiting_sum=0;
|
||||
for(KThread x:waiting_queue)
|
||||
waiting_sum+=thread_effective_tickets.get(x);
|
||||
int win=rng.nextInt(waiting_sum),acc=0;
|
||||
for(KThread x:waiting_queue)
|
||||
if(acc<=win&&win<acc+thread_effective_tickets.get(x))
|
||||
{
|
||||
result=x;
|
||||
break;
|
||||
}
|
||||
else
|
||||
acc+=thread_effective_tickets.get(x);
|
||||
|
||||
if(transfer&&acquiring_process!=null)
|
||||
for(KThread x:waiting_queue)
|
||||
remove_upstream(x,acquiring_process);
|
||||
waiting_queue.remove(result);
|
||||
acquiring_process=result;
|
||||
if(transfer)
|
||||
for(KThread x:waiting_queue)
|
||||
add_upstream(x,acquiring_process);
|
||||
return result;
|
||||
}
|
||||
public void print()
|
||||
{
|
||||
}
|
||||
public boolean transfer;
|
||||
private KThread acquiring_process;
|
||||
private HashSet<KThread> waiting_queue;
|
||||
}
|
||||
|
||||
protected int num_tickets=0;
|
||||
protected static HashMap<KThread,Integer> thread_original_tickets;
|
||||
protected static HashMap<KThread,Integer> thread_effective_tickets;
|
||||
protected static HashMap<KThread,HashMap<KThread,Integer>> upstream;
|
||||
public static final int min_tickets=1;
|
||||
public static final int max_tickets=Integer.MAX_VALUE;
|
||||
protected static Random rng;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ import nachos.machine.*;
|
|||
import nachos.threads.*;
|
||||
import nachos.userprog.*;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* A kernel that can support multiple user processes.
|
||||
*/
|
||||
|
@ -19,14 +23,35 @@ public class UserKernel extends ThreadedKernel {
|
|||
* Initialize this kernel. Creates a synchronized console and sets the
|
||||
* processor's exception handler.
|
||||
*/
|
||||
public void initialize(String[] args) {
|
||||
super.initialize(args);
|
||||
public void initialize(String[] args)
|
||||
{
|
||||
super.initialize(args);
|
||||
|
||||
console = new SynchConsole(Machine.console());
|
||||
|
||||
Machine.processor().setExceptionHandler(new Runnable() {
|
||||
public void run() { exceptionHandler(); }
|
||||
});
|
||||
console = new SynchConsole(Machine.console());
|
||||
|
||||
Machine.processor().setExceptionHandler(new Runnable() {
|
||||
public void run() { exceptionHandler(); }
|
||||
});
|
||||
|
||||
//Initialize free page list
|
||||
|
||||
fp_lock=new Semaphore(1);
|
||||
fp_lock.P();
|
||||
free_pages=new LinkedList<Integer>();
|
||||
int num_phys_pages=Machine.processor().getNumPhysPages();
|
||||
for(int i=0;i<num_phys_pages;i++)
|
||||
free_pages.add(i);
|
||||
fp_lock.V();
|
||||
|
||||
process_lock=new Semaphore(1);
|
||||
process_lock.P();
|
||||
process_table=new HashMap<Integer,UserProcess>();
|
||||
process_return=new HashMap<Integer,Integer>();
|
||||
process_tree=new HashMap<Integer,HashSet<Integer>>();
|
||||
process_fin=new HashMap<Integer,Integer>();
|
||||
process_free_pid=new LinkedList<Integer>();
|
||||
process_pool_size=0;
|
||||
process_lock.V();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,15 +114,15 @@ public class UserKernel extends ThreadedKernel {
|
|||
*
|
||||
* @see nachos.machine.Machine#getShellProgramName
|
||||
*/
|
||||
public void run() {
|
||||
super.run();
|
||||
public void run()
|
||||
{
|
||||
super.run();
|
||||
|
||||
UserProcess process = UserProcess.newUserProcess();
|
||||
|
||||
String shellProgram = Machine.getShellProgramName();
|
||||
Lib.assertTrue(process.execute(shellProgram, new String[] { }));
|
||||
UserProcess process = UserProcess.newUserProcess();
|
||||
String shellProgram = Machine.getShellProgramName();
|
||||
Lib.assertTrue(process.execute(shellProgram, new String[] { }));
|
||||
|
||||
KThread.currentThread().finish();
|
||||
KThread.currentThread().finish();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,6 +134,16 @@ public class UserKernel extends ThreadedKernel {
|
|||
|
||||
/** Globally accessible reference to the synchronized console. */
|
||||
public static SynchConsole console;
|
||||
public static LinkedList<Integer> free_pages;
|
||||
public static Semaphore fp_lock;
|
||||
|
||||
public static HashMap<Integer,UserProcess> process_table;
|
||||
public static HashMap<Integer,HashSet<Integer>> process_tree;
|
||||
public static HashMap<Integer,Integer> process_return;
|
||||
public static HashMap<Integer,Integer> process_fin;
|
||||
public static LinkedList<Integer> process_free_pid;
|
||||
public static Semaphore process_lock;
|
||||
public static int process_pool_size;
|
||||
|
||||
// dummy variables to make javac smarter
|
||||
private static Coff dummy1 = null;
|
||||
|
|
|
@ -5,6 +5,7 @@ import nachos.threads.*;
|
|||
import nachos.userprog.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Encapsulates the state of a user process that is not contained in its
|
||||
|
@ -25,8 +26,12 @@ public class UserProcess {
|
|||
public UserProcess() {
|
||||
int numPhysPages = Machine.processor().getNumPhysPages();
|
||||
pageTable = new TranslationEntry[numPhysPages];
|
||||
cond_lock=new Lock();
|
||||
cond=new Condition(cond_lock);
|
||||
/*
|
||||
for (int i=0; i<numPhysPages; i++)
|
||||
pageTable[i] = new TranslationEntry(i,i, true,false,false,false);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,7 +42,9 @@ public class UserProcess {
|
|||
* @return a new process of the correct class.
|
||||
*/
|
||||
public static UserProcess newUserProcess() {
|
||||
return (UserProcess)Lib.constructObject(Machine.getProcessClassName());
|
||||
//TODO: Remove this line!!!
|
||||
return new UserProcess();
|
||||
//return (UserProcess)Lib.constructObject(Machine.getProcessClassName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,14 +58,25 @@ public class UserProcess {
|
|||
public boolean execute(String name, String[] args) {
|
||||
if (!load(name, args))
|
||||
return false;
|
||||
|
||||
new UThread(this).setName(name).fork();
|
||||
|
||||
descs=new OpenFile[16];
|
||||
descs[0]=UserKernel.console.openForReading();
|
||||
descs[1]=UserKernel.console.openForWriting();
|
||||
for(int i=2;i<16;i++)
|
||||
descs[i]=null;
|
||||
|
||||
UserKernel.process_lock.P();
|
||||
//Simply increment the counter for now
|
||||
UserKernel.process_pool_size+=1;
|
||||
pid=UserKernel.process_pool_size;
|
||||
UserKernel.process_table.put(pid,this);
|
||||
UserKernel.process_tree.put(pid,new HashSet<Integer>());
|
||||
UserKernel.process_fin.put(pid,0);
|
||||
UserKernel.process_lock.V();
|
||||
|
||||
thread=new UThread(this);
|
||||
thread.setName(name).fork();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -98,6 +116,12 @@ public class UserProcess {
|
|||
|
||||
int bytesRead = readVirtualMemory(vaddr, bytes);
|
||||
|
||||
/*
|
||||
System.out.println("Read:");
|
||||
for(int i=0;i<bytesRead;i++)
|
||||
System.out.println(bytes[i]);
|
||||
*/
|
||||
|
||||
for (int length=0; length<bytesRead; length++) {
|
||||
if (bytes[length] == 0)
|
||||
return new String(bytes, 0, length);
|
||||
|
@ -132,20 +156,28 @@ public class UserProcess {
|
|||
* the array.
|
||||
* @return the number of bytes successfully transferred.
|
||||
*/
|
||||
public int readVirtualMemory(int vaddr, byte[] data, int offset,
|
||||
int length) {
|
||||
Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= data.length);
|
||||
public int readVirtualMemory(int vaddr, byte[] data, int offset, int length)
|
||||
{
|
||||
byte[] memory = Machine.processor().getMemory();
|
||||
|
||||
byte[] memory = Machine.processor().getMemory();
|
||||
|
||||
// for now, just assume that virtual addresses equal physical addresses
|
||||
if (vaddr < 0 || vaddr >= memory.length)
|
||||
return 0;
|
||||
int vpn=vaddr/pageSize;
|
||||
if(vaddr<0||vpn>=numPages)
|
||||
return 0;
|
||||
|
||||
int amount = Math.min(length, memory.length-vaddr);
|
||||
System.arraycopy(memory, vaddr, data, offset, amount);
|
||||
|
||||
return amount;
|
||||
int total=0;
|
||||
for(int i=vpn;i<numPages;i++)
|
||||
{
|
||||
int amount=Math.min(length,(i+1)*pageSize-vaddr);
|
||||
int ppn_offs=vaddr-i*pageSize;
|
||||
if(amount<=0)
|
||||
break;
|
||||
System.arraycopy(memory,pageTable[i].ppn*pageSize+ppn_offs,data,offset,amount);
|
||||
offset+=amount;
|
||||
vaddr+=amount;
|
||||
length-=amount;
|
||||
total+=amount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,20 +207,28 @@ public class UserProcess {
|
|||
* virtual memory.
|
||||
* @return the number of bytes successfully transferred.
|
||||
*/
|
||||
public int writeVirtualMemory(int vaddr, byte[] data, int offset,
|
||||
int length) {
|
||||
Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= data.length);
|
||||
public int writeVirtualMemory(int vaddr, byte[] data, int offset, int length)
|
||||
{
|
||||
byte[] memory = Machine.processor().getMemory();
|
||||
|
||||
int vpn=vaddr/pageSize;
|
||||
if(vaddr<0||vpn>=numPages)
|
||||
return 0;
|
||||
|
||||
byte[] memory = Machine.processor().getMemory();
|
||||
|
||||
// for now, just assume that virtual addresses equal physical addresses
|
||||
if (vaddr < 0 || vaddr >= memory.length)
|
||||
return 0;
|
||||
|
||||
int amount = Math.min(length, memory.length-vaddr);
|
||||
System.arraycopy(data, offset, memory, vaddr, amount);
|
||||
|
||||
return amount;
|
||||
int total=0;
|
||||
for(int i=vpn;i<numPages;i++)
|
||||
{
|
||||
int amount=Math.min(length,(i+1)*pageSize-vaddr);
|
||||
int ppn_offs=vaddr-i*pageSize;
|
||||
if(amount<=0)
|
||||
break;
|
||||
System.arraycopy(data,offset,memory,pageTable[i].ppn*pageSize+ppn_offs,amount);
|
||||
offset+=amount;
|
||||
vaddr+=amount;
|
||||
length-=amount;
|
||||
total+=amount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -286,36 +326,56 @@ public class UserProcess {
|
|||
*
|
||||
* @return <tt>true</tt> if the sections were successfully loaded.
|
||||
*/
|
||||
protected boolean loadSections() {
|
||||
if (numPages > Machine.processor().getNumPhysPages()) {
|
||||
coff.close();
|
||||
Lib.debug(dbgProcess, "\tinsufficient physical memory");
|
||||
return false;
|
||||
}
|
||||
protected boolean loadSections()
|
||||
{
|
||||
UserKernel.fp_lock.P();
|
||||
int num_free_pages=UserKernel.free_pages.size();
|
||||
if(numPages>num_free_pages)
|
||||
{
|
||||
coff.close();
|
||||
Lib.debug(dbgProcess,"\tinsufficient physical memory");
|
||||
UserKernel.fp_lock.V();
|
||||
return false;
|
||||
}
|
||||
|
||||
// load sections
|
||||
for (int s=0; s<coff.getNumSections(); s++) {
|
||||
CoffSection section = coff.getSection(s);
|
||||
|
||||
Lib.debug(dbgProcess, "\tinitializing " + section.getName()
|
||||
+ " section (" + section.getLength() + " pages)");
|
||||
//allocate
|
||||
for(int i=0;i<numPages;i++)
|
||||
{
|
||||
Integer x=UserKernel.free_pages.getFirst();
|
||||
pageTable[i]=new TranslationEntry(i,x,true,false,false,false);
|
||||
Lib.debug(dbgProcess,"\tassigning physical page "+x);
|
||||
UserKernel.free_pages.remove(x);
|
||||
}
|
||||
|
||||
for (int i=0; i<section.getLength(); i++) {
|
||||
int vpn = section.getFirstVPN()+i;
|
||||
|
||||
// for now, just assume virtual addresses=physical addresses
|
||||
section.loadPage(i, vpn);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// load sections
|
||||
for (int s=0; s<coff.getNumSections(); s++)
|
||||
{
|
||||
CoffSection section = coff.getSection(s);
|
||||
Lib.debug(dbgProcess, "\tinitializing " + section.getName() + " section (" + section.getLength() + " pages)");
|
||||
for (int i=0; i<section.getLength(); i++)
|
||||
{
|
||||
int vpn = section.getFirstVPN()+i;
|
||||
section.loadPage(i, pageTable[vpn].ppn);
|
||||
}
|
||||
}
|
||||
|
||||
UserKernel.fp_lock.V();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any resources allocated by <tt>loadSections()</tt>.
|
||||
*/
|
||||
protected void unloadSections() {
|
||||
}
|
||||
protected void unloadSections()
|
||||
{
|
||||
UserKernel.fp_lock.P();
|
||||
for(int i=0;i<numPages;i++)
|
||||
{
|
||||
UserKernel.free_pages.add(pageTable[i].ppn);
|
||||
pageTable[i]=null;
|
||||
}
|
||||
UserKernel.fp_lock.V();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the processor's registers in preparation for running the
|
||||
|
@ -343,12 +403,11 @@ public class UserProcess {
|
|||
/**
|
||||
* Handle the halt() system call.
|
||||
*/
|
||||
private int handleHalt() {
|
||||
|
||||
Machine.halt();
|
||||
|
||||
Lib.assertNotReached("Machine.halt() did not halt machine!");
|
||||
return 0;
|
||||
private int handleHalt()
|
||||
{
|
||||
if(pid==1)
|
||||
Machine.halt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -364,6 +423,40 @@ public class UserProcess {
|
|||
syscallClose = 8,
|
||||
syscallUnlink = 9;
|
||||
|
||||
public int handleExit(int status)
|
||||
{
|
||||
UserKernel.process_lock.P();
|
||||
UserKernel.process_fin.put(pid,1);
|
||||
UserKernel.process_return.put(pid,status);
|
||||
UserKernel.process_lock.V();
|
||||
|
||||
cond_lock.acquire();
|
||||
cond.wakeAll();
|
||||
cond_lock.release();
|
||||
|
||||
//Do some extra cleanup
|
||||
unloadSections();
|
||||
coff.close();
|
||||
|
||||
for(int i=0;i<16;i++)
|
||||
if(descs[i]!=null)
|
||||
descs[i].close();
|
||||
|
||||
if(pid==1)
|
||||
Machine.halt();
|
||||
|
||||
thread.finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private byte[] bytearray_create_safe(int size)
|
||||
{
|
||||
if(size<0||size>numPages*pageSize)
|
||||
return null;
|
||||
return new byte[size];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a syscall exception. Called by <tt>handleException()</tt>. The
|
||||
* <i>syscall</i> argument identifies which syscall the user executed:
|
||||
|
@ -394,24 +487,97 @@ public class UserProcess {
|
|||
*/
|
||||
public int handleSyscall(int syscall, int a0, int a1, int a2, int a3)
|
||||
{
|
||||
System.out.println("System Call: "+syscall);
|
||||
String fn;
|
||||
String[] argz;
|
||||
byte[] buf;
|
||||
int len;
|
||||
int len,val,tmp;
|
||||
UserProcess child;
|
||||
boolean status;
|
||||
switch (syscall)
|
||||
{
|
||||
case syscallHalt:
|
||||
return handleHalt();
|
||||
|
||||
case syscallExit:
|
||||
return handleExit(a0);
|
||||
|
||||
case syscallExec:
|
||||
fn=readVirtualMemoryString(a0,256);
|
||||
if(fn!=null&&fn.lastIndexOf('.')!=-1&&fn.substring(fn.lastIndexOf('.')).equals(".coff"))
|
||||
{
|
||||
buf=bytearray_create_safe(4*a1);
|
||||
if(buf==null)
|
||||
return -1;
|
||||
argz=new String[a1];
|
||||
readVirtualMemory(a2,buf,0,4*a1);
|
||||
tmp=0;
|
||||
for(int i=0;i<4*a1;i++)
|
||||
{
|
||||
tmp+=((((int)(buf[i]))&0xFF)<<(8*(i%4)));
|
||||
if(i%4==3)
|
||||
{
|
||||
argz[i/4]=readVirtualMemoryString(tmp,256);
|
||||
if(argz[i/4]==null)
|
||||
argz[i/4]=new String();
|
||||
tmp=0;
|
||||
}
|
||||
}
|
||||
child=UserProcess.newUserProcess();
|
||||
status=child.execute(fn,argz);
|
||||
if(status)
|
||||
{
|
||||
UserKernel.process_lock.P();
|
||||
UserKernel.process_tree.get(pid).add(child.pid);
|
||||
UserKernel.process_lock.V();
|
||||
return child.pid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
|
||||
case syscallJoin:
|
||||
UserKernel.process_lock.P();
|
||||
if(!UserKernel.process_tree.get(pid).contains(a0))
|
||||
{
|
||||
UserKernel.process_lock.V();
|
||||
return -1;
|
||||
}
|
||||
tmp=UserKernel.process_fin.get(a0);
|
||||
if(tmp==1)
|
||||
{
|
||||
val=UserKernel.process_return.get(a0);
|
||||
UserKernel.process_lock.V();
|
||||
}
|
||||
else
|
||||
{
|
||||
child=UserKernel.process_table.get(a0);
|
||||
UserKernel.process_lock.V();
|
||||
|
||||
child.cond_lock.acquire();
|
||||
child.cond.sleep();
|
||||
child.cond_lock.release();
|
||||
|
||||
UserKernel.process_lock.P();
|
||||
val=UserKernel.process_return.get(a0);
|
||||
UserKernel.process_lock.V();
|
||||
}
|
||||
buf=new byte[4];
|
||||
for(int i=0;i<4;i++)
|
||||
buf[i]=(byte)(((val>>(8*i))%(1<<8))&0xFF);
|
||||
writeVirtualMemory(a1,buf,0,4);
|
||||
if(val==-1)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
case syscallCreate:
|
||||
fn=readVirtualMemoryString(a0,256);
|
||||
if(fn!=null)
|
||||
{
|
||||
//System.out.println("I am going to create a file name "+fn);
|
||||
OpenFile tf=ThreadedKernel.fileSystem.open(fn,true);
|
||||
if(tf==null)
|
||||
return -1;
|
||||
for(int i=2;i<16;i++)
|
||||
for(int i=0;i<16;i++)
|
||||
if(descs[i]==null)
|
||||
{
|
||||
descs[i]=tf;
|
||||
|
@ -419,14 +585,12 @@ public class UserProcess {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
System.out.println("Bloody hell");
|
||||
return -1;
|
||||
|
||||
case syscallOpen:
|
||||
fn=readVirtualMemoryString(a0,256);
|
||||
if(fn!=null)
|
||||
{
|
||||
//System.out.println("I am going to open a file name "+fn);
|
||||
OpenFile tf=ThreadedKernel.fileSystem.open(fn,false);
|
||||
if(tf==null)
|
||||
return -1;
|
||||
|
@ -438,26 +602,35 @@ public class UserProcess {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
System.out.println("Bloody hell");
|
||||
return -1;
|
||||
|
||||
case syscallRead:
|
||||
if(a0<0||a0>=16)
|
||||
return -1;
|
||||
if(descs[a0]==null)
|
||||
return -1;
|
||||
buf=new byte[a2];
|
||||
buf=bytearray_create_safe(a2);
|
||||
if(buf==null)
|
||||
return -1;
|
||||
len=descs[a0].read(buf,0,a2);
|
||||
if(len<0)
|
||||
return -1;
|
||||
return writeVirtualMemory(a1,buf,0,len);
|
||||
|
||||
case syscallWrite:
|
||||
if(a0<0||a0>=16)
|
||||
return -1;
|
||||
if(descs[a0]==null)
|
||||
return -1;
|
||||
buf=new byte[a2];
|
||||
buf=bytearray_create_safe(a2);
|
||||
if(buf==null)
|
||||
return -1;
|
||||
len=readVirtualMemory(a1,buf,0,a2);
|
||||
return descs[a0].write(buf,0,len);
|
||||
|
||||
case syscallClose:
|
||||
if(a0<0||a0>=16)
|
||||
return -1;
|
||||
if(descs[a0]!=null)
|
||||
descs[a0].close();
|
||||
descs[a0]=null;
|
||||
|
@ -503,9 +676,10 @@ public class UserProcess {
|
|||
break;
|
||||
|
||||
default:
|
||||
Lib.debug(dbgProcess, "Unexpected exception: " +
|
||||
Processor.exceptionNames[cause]);
|
||||
Lib.assertNotReached("Unexpected exception");
|
||||
Lib.debug(dbgProcess, "Unexpected exception: " + Processor.exceptionNames[cause]);
|
||||
handleExit(-1);
|
||||
|
||||
//Lib.assertNotReached("Unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,4 +700,10 @@ public class UserProcess {
|
|||
private static final int pageSize = Processor.pageSize;
|
||||
private static final char dbgProcess = 'a';
|
||||
private OpenFile descs[];
|
||||
|
||||
public int pid;
|
||||
public Lock cond_lock;
|
||||
public Condition cond;
|
||||
|
||||
private UThread thread;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue