This commit is contained in:
2024-12-30 05:59:42 +08:00
parent bf78b95c9d
commit 72320ede22
42 changed files with 1758 additions and 1556 deletions

View File

@@ -200,18 +200,18 @@ DEFINES = -DFILESYS_STUB -DRDATA -DSIM_FIX
# break the thread system. You might want to use -fno-inline if
# you need to call some inline functions from the debugger.
CFLAGS = -g -Wall -Wextra $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32 # -fsanitize=address,undefined
LDFLAGS = -m32 # -fsanitize=address,undefined
CFLAGS = -g -Wall $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32 -w
LDFLAGS = -m32
CPP_AS_FLAGS= -m32
#####################################################################
CPP=/lib/cpp
CC = g++ -m32 -Wno-deprecated
LD = g++ -m32 -Wno-deprecated
CC = g++ -m32
LD = g++ -m32
AS = as --32
RM = /bin/rm
INCPATH = -I../network -I../filesys -I../userprog -I../threads -I../machine -I../lib -I-
INCPATH = -iquote../network -iquote../filesys -iquote../userprog -iquote../threads -iquote../machine -iquote../lib
PROGRAM = nachos
@@ -332,7 +332,6 @@ S_OFILES = switch.o
OFILES = $(C_OFILES) $(S_OFILES)
$(PROGRAM): $(OFILES)
cat ../test/*.sh ../test/Makefile ../test/*.c
$(LD) $(OFILES) $(LDFLAGS) -o $(PROGRAM)
$(C_OFILES): %.o:

View File

@@ -40,13 +40,15 @@
#ifdef FILESYS_STUB // Temporarily implement file system calls as
// calls to UNIX, until the real file system
// implementation is available
typedef int OpenFileId;
class FileSystem {
public:
FileSystem() { for (int i = 0; i < 20; i++) fileDescriptorTable[i] = NULL; }
bool Create(char* name) {
int fileDescriptor = OpenForWrite(name);
if (fileDescriptor == -1) return FALSE;
Close(fileDescriptor);
return TRUE;
@@ -54,14 +56,64 @@ class FileSystem {
OpenFile* Open(char* name) {
int fileDescriptor = OpenForReadWrite(name, FALSE);
if (fileDescriptor == -1) return NULL;
return new OpenFile(fileDescriptor);
}
OpenFileId OpenFiles(char* name) {
OpenFile* file = Open(name);
if (!file) return -1;
int freeIndex = -1;
for (int i = 0; i < 20; i++)
if (!fileDescriptorTable[i])
freeIndex = i;
if (freeIndex == -1)
return -1;
OpenFileId fileDescriptor = file->GetFileDescriptor();
fileDescriptorTable[freeIndex] = file;
return fileDescriptor;
}
int WriteFile(char* buffer, int size, OpenFileId fd) {
for (int i = 0; i < 20; i++) {
if (!fileDescriptorTable[i])
continue;
if (fileDescriptorTable[i]->GetFileDescriptor() == fd) {
return fileDescriptorTable[i]->Write(buffer, size);
}
}
return -1;
}
int ReadFile(char* buffer, int size, OpenFileId fd) {
for (int i = 0; i < 20; i++) {
if (!fileDescriptorTable[i])
continue;
if (fileDescriptorTable[i]->GetFileDescriptor() == fd)
return fileDescriptorTable[i]->Read(buffer, size);
}
return -1;
}
int CloseFile(OpenFileId fd) {
for (int i = 0; i < 20; i++) {
if (!fileDescriptorTable[i])
continue;
if (fileDescriptorTable[i]->GetFileDescriptor() == fd) {
delete fileDescriptorTable[i];
fileDescriptorTable[i] = NULL;
return 1;
}
}
return 0;
}
bool Remove(char* name) { return Unlink(name) == 0; }
OpenFile* fileDescriptorTable[20];
};
#else // FILESYS

View File

@@ -27,6 +27,8 @@
#ifdef FILESYS_STUB // Temporarily implement calls to
// Nachos file system as calls to UNIX!
// See definitions listed under #else
typedef int OpenFileId;
class OpenFile {
public:
OpenFile(int f) { file = f; currentOffset = 0; } // open the file
@@ -54,6 +56,10 @@ class OpenFile {
int Length() { Lseek(file, 0, 2); return Tell(file); }
OpenFileId GetFileDescriptor() {
return file;
}
private:
int file;
int currentOffset;

View File

@@ -29,6 +29,7 @@ const char dbgFile = 'f'; // file system
const char dbgAddr = 'a'; // address spaces
const char dbgNet = 'n'; // network emulation
const char dbgSys = 'u'; // systemcall
const char dbgSche = 'z';
class Debug {
public:

View File

@@ -308,7 +308,6 @@ int
OpenForWrite(char *name)
{
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
// cerr << "OpenForWrite name, fd: " << (int)name << ", " << fd << endl;
ASSERT(fd >= 0);
return fd;
@@ -326,7 +325,6 @@ int
OpenForReadWrite(char *name, bool crashOnError)
{
int fd = open(name, O_RDWR, 0);
// cerr << "OpenForReadWrite name, fd: " << (int)name << ", " << fd << endl;
ASSERT(!crashOnError || fd >= 0);
return fd;

View File

@@ -172,6 +172,12 @@ ConsoleOutput::PutChar(char ch)
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
}
//----------------------------------------------------------------------
// ConsoleOutput::PutInt()
// Write a int to the simulated display, schedule an interrupt
// to occur in the future, and return.
//----------------------------------------------------------------------
void
ConsoleOutput::PutInt(int value)
{

View File

@@ -76,7 +76,9 @@ class ConsoleOutput : public CallBackObj {
void PutChar(char ch); // Write "ch" to the console display,
// and return immediately. "callWhenDone"
// will called when the I/O completes.
void PutInt(int n);
void PutInt(int value);
void CallBack(); // Invoked when next character can be put
// out to the display.

View File

@@ -22,8 +22,8 @@
#include "copyright.h"
#include "interrupt.h"
#include "main.h"
#include "synchconsole.h"
#include "main.h"
// String definitions for debugging messages
@@ -341,7 +341,7 @@ static void
PrintPending (PendingInterrupt *pending)
{
cout << "Interrupt handler "<< intTypeNames[pending->type];
cout << ", scheduled at " << pending->when << endl;
cout << ", scheduled at " << pending->when;
}
//----------------------------------------------------------------------
@@ -360,8 +360,31 @@ Interrupt::DumpState()
cout << "\nEnd of pending interrupts\n";
}
void
Interrupt::PrintInt(int value)
void Interrupt::PrintInt(int value)
{
kernel->synchConsoleOut->PutInt(value);
}
OpenFileId
Interrupt::OpenFile(char *filename)
{
return kernel->fileSystem->OpenFiles(filename);
}
int
Interrupt::WriteFile(char *buffer, int size, OpenFileId fd)
{
return kernel->fileSystem->WriteFile(buffer, size, fd);
}
int
Interrupt::CloseFile(OpenFileId fd)
{
return kernel->fileSystem->CloseFile(fd);
}
int
Interrupt::ReadFile(char *buffer, int size, OpenFileId fd)
{
return kernel->fileSystem->ReadFile(buffer, size, fd);
}

View File

@@ -37,6 +37,10 @@
#include "list.h"
#include "callback.h"
#include "filesys.h"
typedef int OpenFileId;
// Interrupts can be disabled (IntOff) or enabled (IntOn)
enum IntStatus { IntOff, IntOn };
@@ -48,8 +52,10 @@ enum MachineStatus {IdleMode, SystemMode, UserMode};
// IntType records which hardware device generated an interrupt.
// In Nachos, we support a hardware timer device, a disk, a console
// display and keyboard, and a network.
enum IntType { TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
NetworkSendInt, NetworkRecvInt};
enum IntType {
TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
NetworkSendInt, NetworkRecvInt
};
// The following class defines an interrupt that is scheduled
// to occur in the future. The internal data structures are
@@ -96,6 +102,10 @@ class Interrupt {
void PrintInt(int number);
int CreateFile(char* filename);
OpenFileId OpenFile(char* filename);
int WriteFile(char* buffer, int size, OpenFileId fd);
int CloseFile(OpenFileId fd);
int ReadFile(char* buffer, int size, OpenFileId fd);
void YieldOnReturn(); // cause a context switch on return
// from an interrupt handler

View File

@@ -13,17 +13,10 @@
// Textual names of the exceptions that can be generated by user program
// execution, for debugging.
static char* exceptionNames[] = {
"no exception",
"syscall",
"page fault/no TLB entry",
"page read only",
"bus error",
"address error",
"overflow",
"illegal instruction",
"bad memory allocation"
};
static char* exceptionNames[] = { "no exception", "syscall",
"page fault/no TLB entry", "page read only",
"bus error", "address error", "overflow",
"illegal instruction" };
//----------------------------------------------------------------------
// CheckEndian

View File

@@ -40,8 +40,7 @@ const int NumPhysPages = 128;
const int MemorySize = (NumPhysPages * PageSize);
const int TLBSize = 4; // if there is a TLB, make it small
enum ExceptionType {
NoException, // Everything ok!
enum ExceptionType { NoException, // Everything ok!
SyscallException, // A program executed a system call.
PageFaultException, // No valid translation found
ReadOnlyException, // Write attempted to page marked
@@ -53,7 +52,8 @@ enum ExceptionType {
// address space
OverflowException, // Integer overflow in add or sub.
IllegalInstrException, // Unimplemented or reserved instr.
MemoryLimitException, // Bad allocation
MemoryLimitException, // Insufficient memory
NumExceptionTypes
};

View File

@@ -53,7 +53,10 @@ const int UserTick = 1; // advance for each user-level instruction
const int SystemTick = 10; // advance each time interrupts are enabled
const int RotationTime = 500; // time disk takes to rotate one sector
const int SeekTime = 500; // time disk takes to seek past one track
const int ConsoleTime = 100; // time to read or write one character
// MP4 MODIFIED
const int ConsoleTime = 1; // time to read or write one character
const int NetworkTime = 100; // time to send or receive one packet
const int TimerTicks = 100; // (average) time between timer interrupts

View File

@@ -208,7 +208,6 @@ Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
if (tlb == NULL) { // => page table => vpn is index into table
if (vpn >= pageTableSize) {
DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
DEBUG(dbgAddr, "vpn, pageTableSize, NumPhysPages: " << vpn << ' ' << pageTableSize << ' ' << NumPhysPages);
return AddressErrorException;
} else if (!pageTable[vpn].valid) {
DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
@@ -234,13 +233,6 @@ Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
return ReadOnlyException;
}
pageFrame = entry->physicalPage;
if (pageFrame == -1) {
pageFrame = entry->physicalPage = kernel->frameTable->Allocate();
if (pageFrame == -1) {
DEBUG(dbgAddr, "Memory Limit exceeded");
return MemoryLimitException;
}
}
// if the pageFrame is too big, there is something really wrong!
// An invalid translation was loaded into the page table or TLB.

View File

@@ -113,8 +113,7 @@ ifeq ($(hosttype),unknown)
PROGRAMS = unknownhost
else
# change this if you create a new test program!
PROGRAMS = add halt consoleIO_test1 consoleIO_test2 fileIO_test1 fileIO_test2 test
# PROGRAMS = halt
PROGRAMS = mp4_consoleIO_1 mp4_consoleIO_2 mp4_consoleIO_3 mp4_consoleIO_4
endif
all: $(PROGRAMS)
@@ -122,78 +121,35 @@ all: $(PROGRAMS)
start.o: start.S ../userprog/syscall.h
$(CC) $(CFLAGS) $(ASFLAGS) -c start.S
halt.o: halt.c
$(CC) $(CFLAGS) -c halt.c
halt: halt.o start.o
$(LD) $(LDFLAGS) start.o halt.o -o halt.coff
$(COFF2NOFF) halt.coff halt
mp4_consoleIO_1.o: mp4_consoleIO_1.c
$(CC) $(CFLAGS) -c mp4_consoleIO_1.c
add.o: add.c
$(CC) $(CFLAGS) -c add.c
mp4_consoleIO_1: mp4_consoleIO_1.o start.o
$(LD) $(LDFLAGS) start.o mp4_consoleIO_1.o -o mp4_consoleIO_1.coff
$(COFF2NOFF) mp4_consoleIO_1.coff mp4_consoleIO_1
add: add.o start.o
$(LD) $(LDFLAGS) start.o add.o -o add.coff
$(COFF2NOFF) add.coff add
shell.o: shell.c
$(CC) $(CFLAGS) -c shell.c
shell: shell.o start.o
$(LD) $(LDFLAGS) start.o shell.o -o shell.coff
$(COFF2NOFF) shell.coff shell
mp4_consoleIO_2.o: mp4_consoleIO_2.c
$(CC) $(CFLAGS) -c mp4_consoleIO_2.c
sort.o: sort.c
$(CC) $(CFLAGS) -c sort.c
sort: sort.o start.o
$(LD) $(LDFLAGS) start.o sort.o -o sort.coff
$(COFF2NOFF) sort.coff sort
mp4_consoleIO_2: mp4_consoleIO_2.o start.o
$(LD) $(LDFLAGS) start.o mp4_consoleIO_2.o -o mp4_consoleIO_2.coff
$(COFF2NOFF) mp4_consoleIO_2.coff mp4_consoleIO_2
segments.o: segments.c
$(CC) $(CFLAGS) -c segments.c
segments: segments.o start.o
$(LD) $(LDFLAGS) start.o segments.o -o segments.coff
$(COFF2NOFF) segments.coff segments
mp4_consoleIO_3.o: mp4_consoleIO_3.c
$(CC) $(CFLAGS) -c mp4_consoleIO_3.c
matmult.o: matmult.c
$(CC) $(CFLAGS) -c matmult.c
matmult: matmult.o start.o
$(LD) $(LDFLAGS) start.o matmult.o -o matmult.coff
$(COFF2NOFF) matmult.coff matmult
mp4_consoleIO_3: mp4_consoleIO_3.o start.o
$(LD) $(LDFLAGS) start.o mp4_consoleIO_3.o -o mp4_consoleIO_3.coff
$(COFF2NOFF) mp4_consoleIO_3.coff mp4_consoleIO_3
consoleIO_test1.o: consoleIO_test1.c
$(CC) $(CFLAGS) -c consoleIO_test1.c
consoleIO_test1: consoleIO_test1.o start.o
$(LD) $(LDFLAGS) start.o consoleIO_test1.o -o consoleIO_test1.coff
$(COFF2NOFF) consoleIO_test1.coff consoleIO_test1
mp4_consoleIO_4.o: mp4_consoleIO_4.c
$(CC) $(CFLAGS) -c mp4_consoleIO_4.c
consoleIO_test2.o: consoleIO_test2.c
$(CC) $(CFLAGS) -c consoleIO_test2.c
consoleIO_test2: consoleIO_test2.o start.o
$(LD) $(LDFLAGS) start.o consoleIO_test2.o -o consoleIO_test2.coff
$(COFF2NOFF) consoleIO_test2.coff consoleIO_test2
mp4_consoleIO_4: mp4_consoleIO_4.o start.o
$(LD) $(LDFLAGS) start.o mp4_consoleIO_4.o -o mp4_consoleIO_4.coff
$(COFF2NOFF) mp4_consoleIO_4.coff mp4_consoleIO_4
fileIO_test1.o: fileIO_test1.c
$(CC) $(CFLAGS) -c fileIO_test1.c
fileIO_test1: fileIO_test1.o start.o
$(LD) $(LDFLAGS) start.o fileIO_test1.o -o fileIO_test1.coff
$(COFF2NOFF) fileIO_test1.coff fileIO_test1
fileIO_test2.o: fileIO_test2.c
$(CC) $(CFLAGS) -c fileIO_test2.c
fileIO_test2: fileIO_test2.o start.o
$(LD) $(LDFLAGS) start.o fileIO_test2.o -o fileIO_test2.coff
$(COFF2NOFF) fileIO_test2.coff fileIO_test2
fileIO_test3.o: fileIO_test3.c
$(CC) $(CFLAGS) -c fileIO_test3.c
fileIO_test3: fileIO_test3.o start.o
$(LD) $(LDFLAGS) start.o fileIO_test3.o -o fileIO_test3.coff
$(COFF2NOFF) fileIO_test3.coff fileIO_test3
test.o: test.c
$(CC) $(CFLAGS) -c test.c
test: test.o start.o
$(LD) $(LDFLAGS) start.o test.o -o test.coff
$(COFF2NOFF) test.coff test
clean:
$(RM) -f *.o *.ii
@@ -203,12 +159,11 @@ distclean: clean
$(RM) -f $(PROGRAMS)
run: $(PROGRAMS)
timeout 1 $(NACHOS) -e consoleIO_test1 -e consoleIO_test2
timeout 1 $(NACHOS) -ep mp4_consoleIO_1 70 -ep mp4_consoleIO_3 80 -ep mp4_consoleIO_2 50
echo 'done'
debug: $(PROGRAMS)
timeout 1 $(NACHOS) -e consoleIO_test1 -e consoleIO_test2 -d +
timeout 1 $(NACHOS) -d z -ep mp4_consoleIO_1 60 -ep mp4_consoleIO_2 70
unknownhost:
@echo Host type could not be determined.

View File

@@ -0,0 +1,10 @@
#include "syscall.h"
int main()
{
int n;
for (n = 0; n < 4; n++) {
PrintInt(1);
}
return 0;
}

View File

@@ -0,0 +1,9 @@
#include "syscall.h"
int main()
{
int n;
for (n = 0; n < 5; n++) {
PrintInt(2);
}
return 0;
}

View File

@@ -0,0 +1,10 @@
#include "syscall.h"
int
main()
{
int n;
for (n = 0; n < 12; n++) {
PrintInt(3);
}
return 0;
}

View File

@@ -0,0 +1,9 @@
#include "syscall.h"
int main()
{
int n;
for (n = 0; n < 11; n++) {
PrintInt(4);
}
return 0;
}

View File

@@ -1,4 +1,9 @@
make distclean
make
timeout 1 ../build.linux/nachos -e consoleIO_test1 -e consoleIO_test2
echo 'done'
rm -f *.o *.ii
rm -f *.coff
echo "=========================="
timeout 1 ../build.linux/nachos -e mp4_consoleIO_1 -e mp4_consoleIO_2
echo "=========================="
timeout 1 ../build.linux/nachos -e mp4_consoleIO_3 -e mp4_consoleIO_4
echo "done"

View File

@@ -58,6 +58,14 @@ MSG:
j $31
.end MSG
.globl PrintInt
.ent PrintInt
PrintInt:
addiu $2,$0,SC_PrintInt
syscall
j $31
.end PrintInt
.globl Add
.ent Add
Add:
@@ -186,14 +194,6 @@ ThreadJoin:
j $31
.end ThreadJoin
.globl PrintInt
.ent PrintInt
PrintInt:
addiu $2,$0,SC_PrintInt
syscall
j $31
.end PrintInt
/* dummy function to keep gcc happy */
.globl __main

View File

@@ -49,7 +49,9 @@ Alarm::CallBack()
Interrupt* interrupt = kernel->interrupt;
MachineStatus status = interrupt->getStatus();
// Todo ----
if (status != IdleMode) {
interrupt->YieldOnReturn();
// interrupt->YieldOnReturn();
}
// ---------
}

View File

@@ -26,8 +26,6 @@
Kernel::Kernel(int argc, char** argv)
{
execfileNum = 0;
threadNum = 0;
randomSlice = FALSE;
debugUserProg = FALSE;
consoleIn = NULL; // default is stdin
@@ -45,32 +43,48 @@ Kernel::Kernel(int argc, char **argv)
// number generator
randomSlice = TRUE;
i++;
} else if (strcmp(argv[i], "-s") == 0) {
}
else if (strcmp(argv[i], "-s") == 0) {
debugUserProg = TRUE;
} else if (strcmp(argv[i], "-e") == 0) {
}
// Todo ----
else if (strcmp(argv[i], "-e") == 0) {
execfile[++execfileNum] = argv[++i];
cout << execfile[execfileNum] << "\n";
} else if (strcmp(argv[i], "-ci") == 0) {
}
else if (strcmp(argv[i], "-ep") == 0) {
execfile[++execfileNum] = argv[++i];
execPriority[execfileNum] = atoi(argv[++i]);
cout << execfile[execfileNum] << " with priority "
<< execPriority[execfileNum] << "\n";
}
// ---------
else if (strcmp(argv[i], "-ci") == 0) {
ASSERT(i + 1 < argc);
consoleIn = argv[i + 1];
i++;
} else if (strcmp(argv[i], "-co") == 0) {
}
else if (strcmp(argv[i], "-co") == 0) {
ASSERT(i + 1 < argc);
consoleOut = argv[i + 1];
i++;
#ifndef FILESYS_STUB
} else if (strcmp(argv[i], "-f") == 0) {
}
else if (strcmp(argv[i], "-f") == 0) {
formatFlag = TRUE;
#endif
} else if (strcmp(argv[i], "-n") == 0) {
}
else if (strcmp(argv[i], "-n") == 0) {
ASSERT(i + 1 < argc); // next argument is float
reliability = atof(argv[i + 1]);
i++;
} else if (strcmp(argv[i], "-m") == 0) {
}
else if (strcmp(argv[i], "-m") == 0) {
ASSERT(i + 1 < argc); // next argument is int
hostName = atoi(argv[i + 1]);
i++;
} else if (strcmp(argv[i], "-u") == 0) {
}
else if (strcmp(argv[i], "-u") == 0) {
cout << "Partial usage: nachos [-rs randomSeed]\n";
cout << "Partial usage: nachos [-s]\n";
cout << "Partial usage: nachos [-ci consoleIn] [-co consoleOut]\n";
@@ -113,10 +127,12 @@ Kernel::Initialize()
#else
fileSystem = new FileSystem(formatFlag);
#endif // FILESYS_STUB
postOfficeIn = new PostOfficeInput(10);
postOfficeOut = new PostOfficeOutput(reliability);
frameTable = new FrameTable;
// MP4 MODIFIED
// postOfficeIn = new PostOfficeInput(10);
// postOfficeOut = new PostOfficeOutput(reliability);
frameTable = new FrameTable();
interrupt->Enable();
}
@@ -136,8 +152,11 @@ Kernel::~Kernel()
delete synchConsoleOut;
delete synchDisk;
delete fileSystem;
delete postOfficeIn;
delete postOfficeOut;
// MP4 MODIFIED
// delete postOfficeIn;
// delete postOfficeOut;
delete frameTable;
Exit(0);
@@ -254,29 +273,34 @@ Kernel::NetworkTest() {
void ForkExecute(Thread* t)
{
if (!t->space->Load(t->getName()))
if (!t->space->Load(t->getName())) {
return; // executable not found
}
t->space->Execute(t->getName());
}
void Kernel::ExecAll()
{
for (int i = 1;i <= execfileNum;i++) {
int a = Exec(execfile[i]);
int a = Exec(execfile[i], execPriority[i]);
}
currentThread->Finish();
//Kernel::Exec();
}
int Kernel::Exec(char* name)
// Todo ----
int Kernel::Exec(char* name, int priority)
{
t[threadNum] = new Thread(name, threadNum);
t[threadNum]->setPriority(priority);
// ---------
t[threadNum]->space = new AddrSpace();
t[threadNum]->Fork((VoidFunctionPtr)&ForkExecute, (void*)t[threadNum]);
threadNum++;
return threadNum++;
return threadNum - 1;
/*
cout << "Total threads number is " << execfileNum << endl;
for (int n=1;n<=execfileNum;n++) {
@@ -309,7 +333,4 @@ int Kernel::CreateFile(char *filename)
return fileSystem->Create(filename);
}
void Kernel::PrintInt(int value)
{
return synchConsoleOut->PutInt(value);
}

View File

@@ -25,7 +25,8 @@ class SynchConsoleInput;
class SynchConsoleOutput;
class SynchDisk;
// Todo ----
// ---------
class Kernel {
public:
@@ -37,15 +38,17 @@ class Kernel {
// from constructor because
// refers to "kernel" as a global
void ExecAll();
int Exec(char* name);
// Todo ----
int Exec(char* name, int priority);
// ---------
void ThreadSelfTest(); // self test of threads and synchronization
void ConsoleTest(); // interactive console self test
void NetworkTest(); // interactive 2-machine network test
Thread* getThread(int threadID){return t[threadID];}
void PrintInt(int n);
int CreateFile(char* filename); // fileSystem call
// These are public for notational convenience; really,
@@ -64,13 +67,17 @@ class Kernel {
PostOfficeInput *postOfficeIn;
PostOfficeOutput *postOfficeOut;
FrameTable *frameTable;
int hostName; // machine identifier
private:
Thread* t[10];
// Todo ----
char* execfile[10];
int execPriority[10];
// ---------
int execfileNum;
int threadNum;
bool randomSlice; // enable pseudo-random time slicing
@@ -85,5 +92,3 @@ class Kernel {
#endif // KERNEL_H

View File

@@ -22,6 +22,7 @@
#include "debug.h"
#include "scheduler.h"
#include "main.h"
#include <functional>
//----------------------------------------------------------------------
// Scheduler::Scheduler
@@ -29,9 +30,20 @@
// Initially, no ready threads.
//----------------------------------------------------------------------
// Todo ----
int cmp(Thread *a, Thread *b)
{
int ap = a->getPriority();
int bp = b->getPriority();
return (ap < bp) - (ap > bp);
}
Scheduler::Scheduler()
{
readyList = new List<Thread *>;
readyList = new SortedList(cmp);
// ---------
toBeDestroyed = NULL;
}
@@ -60,7 +72,9 @@ Scheduler::ReadyToRun (Thread *thread)
DEBUG(dbgThread, "Putting thread on ready list: " << thread->getName());
//cout << "Putting thread on ready list: " << thread->getName() << endl ;
thread->setStatus(READY);
readyList->Append(thread);
DEBUG(dbgSche, "[A] Tick [" << kernel->stats->totalTicks << "]: Process [" << thread->getName() << "] is inserted into queue.");
readyList->Insert(thread);
}
//----------------------------------------------------------------------
@@ -78,7 +92,9 @@ Scheduler::FindNextToRun ()
if (readyList->IsEmpty()) {
return NULL;
} else {
}
else {
DEBUG(dbgSche, "[B] Tick [" << kernel->stats->totalTicks << "]: Process [" << readyList->Front()->getName() << "] is removed from queue.");
return readyList->RemoveFront();
}
}
@@ -124,6 +140,7 @@ Scheduler::Run (Thread *nextThread, bool finishing)
nextThread->setStatus(RUNNING); // nextThread is now running
DEBUG(dbgThread, "Switching from: " << oldThread->getName() << " to: " << nextThread->getName());
DEBUG(dbgSche, "[C] Tick [" << kernel->stats->totalTicks << "]: Process [" << nextThread->getName() << "] is now selected for execution, thread [" << oldThread->getName() << "] is replaced.");
// This is a machine-dependent assembly language routine defined
// in switch.s. You may have to think

View File

@@ -35,8 +35,11 @@ class Scheduler {
// SelfTest for scheduler is implemented in class Thread
private:
List<Thread *> *readyList; // queue of threads that are ready to run,
// Todo ----
SortedList<Thread *> *readyList; // queue of threads that are ready to run,
// but not running
// ---------
Thread *toBeDestroyed; // finishing thread to be destroyed
// by the next thread that runs
};

View File

@@ -40,7 +40,8 @@ Thread::Thread(char* threadName, int threadID)
stackTop = NULL;
stack = NULL;
status = JUST_CREATED;
for (int i = 0; i < MachineStateSize; i++) {
for (int i = 0; i < MachineStateSize; i++)
{
machineState[i] = NULL; // not strictly necessary, since
// new thread ignores contents
// of machine registers
@@ -88,8 +89,7 @@ Thread::~Thread()
// "arg" is a single argument to be passed to the procedure.
//----------------------------------------------------------------------
void
Thread::Fork(VoidFunctionPtr func, void *arg)
void Thread::Fork(VoidFunctionPtr func, void *arg)
{
Interrupt *interrupt = kernel->interrupt;
Scheduler *scheduler = kernel->scheduler;
@@ -119,10 +119,10 @@ Thread::Fork(VoidFunctionPtr func, void *arg)
// Don't do this: void foo() { int bigArray[10000]; ... }
//----------------------------------------------------------------------
void
Thread::CheckOverflow()
void Thread::CheckOverflow()
{
if (stack != NULL)
{
if (stack != NULL) {
#ifdef HPUX // Stacks grow upward on the Snakes
ASSERT(stack[StackSize - 1] == STACK_FENCEPOST);
#else
@@ -142,8 +142,7 @@ Thread::CheckOverflow()
// 2. enable interrupts (so we can get time-sliced)
//----------------------------------------------------------------------
void
Thread::Begin ()
void Thread::Begin()
{
ASSERT(this == kernel->currentThread);
DEBUG(dbgThread, "Beginning thread: " << name);
@@ -167,8 +166,7 @@ Thread::Begin ()
//----------------------------------------------------------------------
//
void
Thread::Finish ()
void Thread::Finish()
{
(void)kernel->interrupt->SetLevel(IntOff);
ASSERT(this == kernel->currentThread);
@@ -178,7 +176,6 @@ Thread::Finish ()
// not reached
}
//----------------------------------------------------------------------
// Thread::Yield
// Relinquish the CPU if any other thread is ready to run.
@@ -197,8 +194,7 @@ Thread::Finish ()
// Similar to Thread::Sleep(), but a little different.
//----------------------------------------------------------------------
void
Thread::Yield ()
void Thread::Yield()
{
Thread *nextThread;
IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);
@@ -208,7 +204,8 @@ Thread::Yield ()
DEBUG(dbgThread, "Yielding thread: " << name);
nextThread = kernel->scheduler->FindNextToRun();
if (nextThread != NULL) {
if (nextThread != NULL)
{
kernel->scheduler->ReadyToRun(this);
kernel->scheduler->Run(nextThread, FALSE);
}
@@ -235,8 +232,7 @@ Thread::Yield ()
// so that there can't be a time slice between pulling the first thread
// off the ready list, and switching to it.
//----------------------------------------------------------------------
void
Thread::Sleep (bool finishing)
void Thread::Sleep(bool finishing)
{
Thread *nextThread;
@@ -247,7 +243,8 @@ Thread::Sleep (bool finishing)
status = BLOCKED;
// cout << "debug Thread::Sleep " << name << "wait for Idle\n";
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL) {
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL)
{
kernel->interrupt->Idle(); // no one to run, wait for an interrupt
}
// returns when it's time for us to run
@@ -279,11 +276,14 @@ PLabelToAddr(void *plabel)
{
int funcPtr = (int)plabel;
if (funcPtr & 0x02) {
if (funcPtr & 0x02)
{
// L-Field is set. This is a PLT pointer
funcPtr -= 2; // Get rid of the L bit
return (*(void **)funcPtr);
} else {
}
else
{
// L-field not set.
return plabel;
}
@@ -302,8 +302,7 @@ PLabelToAddr(void *plabel)
// "arg" is the parameter to be passed to the procedure
//----------------------------------------------------------------------
void
Thread::StackAllocate (VoidFunctionPtr func, void *arg)
void Thread::StackAllocate(VoidFunctionPtr func, void *arg)
{
stack = (int *)AllocBoundedArray(StackSize * sizeof(int));
@@ -336,7 +335,6 @@ Thread::StackAllocate (VoidFunctionPtr func, void *arg)
*stack = STACK_FENCEPOST;
#endif
#ifdef x86
// the x86 passes the return address on the stack. In order for SWITCH()
// to go to ThreadRoot when we switch to this thread, the return addres
@@ -372,8 +370,7 @@ Thread::StackAllocate (VoidFunctionPtr func, void *arg)
// while executing kernel code. This routine saves the former.
//----------------------------------------------------------------------
void
Thread::SaveUserState()
void Thread::SaveUserState()
{
for (int i = 0; i < NumTotalRegs; i++)
userRegisters[i] = kernel->machine->ReadRegister(i);
@@ -388,14 +385,12 @@ Thread::SaveUserState()
// while executing kernel code. This routine restores the former.
//----------------------------------------------------------------------
void
Thread::RestoreUserState()
void Thread::RestoreUserState()
{
for (int i = 0; i < NumTotalRegs; i++)
kernel->machine->WriteRegister(i, userRegisters[i]);
}
//----------------------------------------------------------------------
// SimpleThread
// Loop 5 times, yielding the CPU to another ready thread
@@ -410,7 +405,8 @@ SimpleThread(int which)
{
int num;
for (num = 0; num < 5; num++) {
for (num = 0; num < 5; num++)
{
cout << "*** thread " << which << " looped " << num << " times\n";
kernel->currentThread->Yield();
}
@@ -422,8 +418,7 @@ SimpleThread(int which)
// to call SimpleThread, and then calling SimpleThread ourselves.
//----------------------------------------------------------------------
void
Thread::SelfTest()
void Thread::SelfTest()
{
DEBUG(dbgThread, "Entering Thread::SelfTest");
@@ -433,3 +428,16 @@ Thread::SelfTest()
kernel->currentThread->Yield();
SimpleThread(0);
}
// Todo ----
int Thread::getPriority() const
{
return priority;
}
void Thread::setPriority(int p)
{
ASSERT(p >= 0 && p <= 149);
priority = p;
}
// ---------

View File

@@ -80,6 +80,10 @@ class Thread {
int *stackTop; // the current stack pointer
void *machineState[MachineStateSize]; // all registers except for stackTop
// Todo ----
int priority;
// ---------
public:
Thread(char* debugName, int threadID); // initialize a Thread
~Thread(); // deallocate a Thread
@@ -89,6 +93,11 @@ class Thread {
// basic thread operations
// Todo ----
int getPriority() const;
void setPriority(int p);
// ---------
void Fork(VoidFunctionPtr func, void *arg);
// Make thread run (*func)(arg)
void Yield(); // Relinquish the CPU if any

View File

@@ -27,7 +27,6 @@
// object file header, in case the file was generated on a little
// endian machine, and we're now running on a big endian machine.
//----------------------------------------------------------------------
static void
SwapHeader(NoffHeader* noffH)
{
@@ -57,71 +56,6 @@ SwapHeader (NoffHeader *noffH)
#endif
}
FrameTable::Node::Node(int idx):
next(nullptr), idx(idx) {}
FrameTable::FrameTable()
{
available = NumPhysPages;
useCount = new int[NumPhysPages];
begin = end = new FrameTable::Node;
for (int i = 0; i < NumPhysPages; i++) {
useCount[i] = 0;
end->idx = i;
end->next = new FrameTable::Node;
end = end->next;
}
}
FrameTable::~FrameTable()
{
delete[] useCount;
while (begin != end) {
FrameTable::Node *tmpNode = begin;
begin = begin->next;
delete tmpNode;
}
delete begin;
}
int FrameTable::Allocate()
{
if (available == 0)
return -1;
int ret = begin->idx;
Node *tmp = begin;
begin = begin->next;
delete tmp;
--available;
useCount[ret]++;
bzero(kernel->machine->mainMemory + ret * PageSize, PageSize);
//cerr << "Allocated at page: " << ret << endl;
return ret;
}
void FrameTable::Release(int phyPageNum)
{
useCount[phyPageNum]--;
if (useCount[phyPageNum] > 0)
return;
++available;
//cerr << "Release page: " << end->idx << endl;
end->idx = phyPageNum;
end->next = new FrameTable::Node;
}
size_t FrameTable::RemainSize()
{
return available;
}
//----------------------------------------------------------------------
// AddrSpace::AddrSpace
// Create an address space to run a user program.
@@ -129,9 +63,24 @@ size_t FrameTable::RemainSize()
// memory. For now, this is really simple (1:1), since we are
// only uniprogramming, and we have a single unsegmented page table
//----------------------------------------------------------------------
AddrSpace::AddrSpace()
{}
{
pageTable = NULL; // initialize with NULL
/*
pageTable = new TranslationEntry[NumPhysPages];
for (int i = 0; i < NumPhysPages; i++) {
pageTable[i].virtualPage = i; // for now, virt page # = phys page #
pageTable[i].physicalPage = i;
pageTable[i].valid = TRUE;
pageTable[i].use = FALSE;
pageTable[i].dirty = FALSE;
pageTable[i].readOnly = FALSE;
}
// zero out the entire address space
bzero(kernel->machine->mainMemory, MemorySize);
*/
}
//----------------------------------------------------------------------
// AddrSpace::~AddrSpace
@@ -140,10 +89,9 @@ AddrSpace::AddrSpace()
AddrSpace::~AddrSpace()
{
for (int i = 0; i < NumPhysPages; i++)
if (pageTable[i].use == TRUE)
kernel->frameTable->Release(pageTable[i].physicalPage);
delete[] pageTable;
/* delete pageTable; */
// release frame table by page table
kernel->frameTable->Release(pageTable, numPages);
}
@@ -156,11 +104,9 @@ AddrSpace::~AddrSpace()
//
// "fileName" is the file containing the object code to load into memory
//----------------------------------------------------------------------
bool
AddrSpace::Load(char* fileName)
{
//cerr << "AddrSpace::Load" << endl;
OpenFile* executable = kernel->fileSystem->Open(fileName);
NoffHeader noffH;
unsigned int size;
@@ -180,11 +126,6 @@ AddrSpace::Load(char *fileName)
// how big is address space?
size = noffH.code.size + noffH.readonlyData.size + noffH.initData.size +
noffH.uninitData.size + UserStackSize;
//cerr << noffH.code.size << ' '
// << noffH.readonlyData.size << ' '
// << noffH.initData.size << ' '
// << noffH.uninitData.size << ' '
// << UserStackSize << endl;
// we need to increase the size
// to leave room for the stack
#else
@@ -192,57 +133,74 @@ AddrSpace::Load(char *fileName)
size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
+ UserStackSize; // we need to increase the size
// to leave room for the stack
//cerr << noffH.code.size << ' '
// << noffH.initData.size << ' '
// << noffH.uninitData.size << ' '
// << UserStackSize << endl;
#endif
numPages = divRoundUp(size, PageSize);
size = numPages * PageSize;
ASSERT(numPages <= NumPhysPages); // check we're not trying
// to run anything too big --
// at least until we have
// virtual memory
pageTable = new TranslationEntry[numPages];
for (int i = 0; i < numPages; i++) {
pageTable[i].virtualPage = i;
pageTable[i].physicalPage = -1;
pageTable[i].valid = TRUE;
pageTable[i].use = FALSE;
pageTable[i].dirty = FALSE;
pageTable[i].readOnly = FALSE;
pageTable = kernel->frameTable->Allocate(numPages);
if (!pageTable) {
kernel->interrupt->setStatus(SystemMode);
ExceptionHandler(MemoryLimitException);
kernel->interrupt->setStatus(UserMode);
}
DEBUG(dbgAddr, "Initializing address space: " << numPages << ", " << size);
// then, copy in the code and data segments into memory
uint paddr; // physical address
ExceptionType ex; // occurring exception
int sz, // total size to load
vaddr, // base virtual address
fpos, // base file position
to_load; // size to load on each time
if (noffH.code.size > 0) {
DEBUG(dbgAddr, "Initializing code segment.");
DEBUG(dbgAddr, noffH.code.virtualAddr << ", " << noffH.code.size);
for (size_t cur = 0; cur < (size_t)noffH.code.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.code.size - cur);
Translate(noffH.code.virtualAddr + cur, &physAddr, 1);
//cerr << "physAddr, size: " << physAddr << ' ' << size << endl;
sz = noffH.code.size;
vaddr = noffH.code.virtualAddr;
fpos = noffH.code.inFileAddr;
for (uint offset = 0; offset < sz; offset += PageSize) {
ex = Translate(vaddr + offset, &paddr, 1);
if (ex != NoException) {
kernel->interrupt->setStatus(SystemMode);
ExceptionHandler(ex);
kernel->interrupt->setStatus(UserMode);
}
to_load = offset + PageSize < sz ? PageSize : sz - offset;
executable->ReadAt(
&(kernel->machine->mainMemory[physAddr]), size,
noffH.code.inFileAddr + cur);
&(kernel->machine->mainMemory[paddr]),
to_load, fpos + offset);
}
}
if (noffH.initData.size > 0) {
DEBUG(dbgAddr, "Initializing data segment.");
DEBUG(dbgAddr, noffH.initData.virtualAddr << ", " << noffH.initData.size);
for (size_t cur = 0; cur < (size_t)noffH.initData.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.initData.size - cur);
Translate(noffH.initData.virtualAddr + cur, &physAddr, 1);
sz = noffH.initData.size;
vaddr = noffH.initData.virtualAddr;
fpos = noffH.initData.inFileAddr;
for (uint offset = 0; offset < sz; offset += PageSize) {
ex = Translate(vaddr + offset, &paddr, 1);
if (ex != NoException) {
kernel->interrupt->setStatus(SystemMode);
ExceptionHandler(ex);
kernel->interrupt->setStatus(UserMode);
}
to_load = offset + PageSize < sz ? PageSize : sz - offset;
executable->ReadAt(
&(kernel->machine->mainMemory[physAddr]), size,
noffH.initData.inFileAddr + cur);
&(kernel->machine->mainMemory[paddr]),
to_load, fpos + offset);
}
}
@@ -251,13 +209,29 @@ AddrSpace::Load(char *fileName)
DEBUG(dbgAddr, "Initializing read only data segment.");
DEBUG(dbgAddr, noffH.readonlyData.virtualAddr << ", " << noffH.readonlyData.size);
for (size_t cur = 0; cur < (size_t)noffH.readonlyData.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.readonlyData.size - cur);
Translate(noffH.readonlyData.virtualAddr + cur, &physAddr, 1);
sz = noffH.readonlyData.size;
vaddr = noffH.readonlyData.virtualAddr;
fpos = noffH.readonlyData.inFileAddr;
// read only flag for page table
for (int i = 0, lim = divRoundUp(sz, PageSize),
from = vaddr / PageSize; i < lim; ++i)
pageTable[from + i].readOnly = TRUE;
for (uint offset = 0; offset < sz; offset += PageSize) {
ex = Translate(vaddr + offset, &paddr, 0); // read only
if (ex != NoException) {
kernel->interrupt->setStatus(SystemMode);
ExceptionHandler(ex);
kernel->interrupt->setStatus(UserMode);
}
to_load = offset + PageSize < sz ? PageSize : sz - offset;
executable->ReadAt(
&(kernel->machine->mainMemory[physAddr]),
size, noffH.readonlyData.inFileAddr + cur);
&(kernel->machine->mainMemory[paddr]),
to_load, fpos + offset);
}
}
#endif
@@ -274,17 +248,16 @@ AddrSpace::Load(char *fileName)
// the address space
//
//----------------------------------------------------------------------
void
AddrSpace::Execute(char* fileName)
{
//cerr << "AddrSpace::Execute" << endl;
kernel->currentThread->space = this;
this->InitRegisters(); // set the initial register values
this->RestoreState(); // load page table register
kernel->machine->Run(); // jump to the user progam
kernel->machine->Run(); // jump to the user program
ASSERTNOTREACHED(); // machine->Run never returns;
// the address space exits
@@ -301,7 +274,6 @@ AddrSpace::Execute(char* fileName)
// will be saved/restored into the currentThread->userRegisters
// when this thread is context switched out.
//----------------------------------------------------------------------
void
AddrSpace::InitRegisters()
{
@@ -335,9 +307,9 @@ AddrSpace::InitRegisters()
//
// For now, don't need to save anything!
//----------------------------------------------------------------------
void AddrSpace::SaveState()
{}
{
}
//----------------------------------------------------------------------
// AddrSpace::RestoreState
@@ -346,7 +318,6 @@ void AddrSpace::SaveState()
//
// For now, tell the machine where to find the page table.
//----------------------------------------------------------------------
void AddrSpace::RestoreState()
{
kernel->machine->pageTable = pageTable;
@@ -381,13 +352,6 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
}
pfn = pte->physicalPage;
if (pfn == -1) {
pfn = pte->physicalPage = kernel->frameTable->Allocate();
if (pfn == -1) {
DEBUG(dbgAddr, "Memory Limit exceeded");
return MemoryLimitException;
}
}
// if the pageFrame is too big, there is something really wrong!
// An invalid translation was loaded into the page table or TLB.
@@ -410,3 +374,44 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
return NoException;
}
FrameTable::FrameTable() {
for (int i = 0; i < NumPhysPages; ++i)
available.Append(i);
}
FrameTable::~FrameTable() {}
uint FrameTable::RemainSize() { return available.NumInList(); }
PageTable FrameTable::Allocate(uint pageNum) {
// if not enough memory
if (RemainSize() < pageNum)
return NULL;
PageTable ptb = new TranslationEntry[pageNum];
for (int i = 0; i < pageNum; ++i) {
ptb[i].virtualPage = i;
int f = available.RemoveFront(); // frame number
ptb[i].physicalPage = f;
// initialize flags
ptb[i].valid = TRUE;
ptb[i].use = FALSE;
ptb[i].dirty = FALSE;
ptb[i].readOnly = FALSE;
// zero out the entire address space
bzero(kernel->machine->mainMemory + f * PageSize, PageSize);
}
return ptb;
}
void FrameTable::Release(PageTable ptb, int pageNum) {
if (!ptb)
return; // nothing to release
for (int i = 0; i < pageNum; ++i)
available.Append(ptb[i].physicalPage);
delete[] ptb;
}

View File

@@ -18,28 +18,6 @@
#define UserStackSize 1024 // increase this as necessary!
class FrameTable {
public:
FrameTable();
~FrameTable();
int Allocate();
void Release(int phyPageNum);
size_t RemainSize();
private:
struct Node {
Node *next;
int idx;
Node(int idx = -1);
};
Node *begin, *end;
size_t available;
int *useCount;
};
class AddrSpace {
public:
AddrSpace(); // Create an address space.
@@ -62,7 +40,8 @@ class AddrSpace {
ExceptionType Translate(unsigned int vaddr, unsigned int* paddr, int mode);
private:
TranslationEntry *pageTable;
TranslationEntry* pageTable; // Assume linear page table translation
// for now!
unsigned int numPages; // Number of pages in the virtual
// address space
@@ -72,3 +51,51 @@ class AddrSpace {
};
#endif // ADDRSPACE_H
#ifndef FRAME_TABLE_H
#define FRAME_TABLE_H
#include "machine.h"
#include "list.h"
/**
* Data structure of Virtual Memory
*/
typedef TranslationEntry* PageTable;
/**
* Data structure of Physical Memory
*/
class FrameTable {
public:
/**
* Initialize a frame table
*/
FrameTable();
~FrameTable();
/**
* Allocate pageNum of frames (pages) and collect
* corresponding translation information into a page table.
*
* @param pageNum numbers of pages
* @return a new Page table, NULL if not enough memory space
*/
PageTable Allocate(uint pageNum);
/**
* Release the physical memory frame
* which the info stored in PageTable
*/
void Release(PageTable ptb, int pageNum);
/**
* @return the remaining numbers of entry of the frame table
*/
uint RemainSize();
private:
List<int> available;
};
#endif /* FRAME_TABLE_H */

View File

@@ -54,6 +54,7 @@ ExceptionHandler(ExceptionType which)
int type = kernel->machine->ReadRegister(2);
int val;
int status, exit, threadID, programID;
int fd, size;
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
switch (which) {
case SyscallException:
@@ -74,6 +75,13 @@ ExceptionHandler(ExceptionType which)
SysHalt();
ASSERTNOTREACHED();
break;
case SC_PrintInt:
val = kernel->machine->ReadRegister(4);
SysPrintInt(val);
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
case SC_Create:
val = kernel->machine->ReadRegister(4);
{
@@ -88,6 +96,62 @@ ExceptionHandler(ExceptionType which)
return;
ASSERTNOTREACHED();
break;
case SC_Open:
val = kernel->machine->ReadRegister(4);
{
char* filename = &(kernel->machine->mainMemory[val]);
//cout << filename << endl;
fd = SysOpen(filename);
kernel->machine->WriteRegister(2, (int)fd);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Write:
val = kernel->machine->ReadRegister(4);
size = kernel->machine->ReadRegister(5);
fd = kernel->machine->ReadRegister(6);
{
char* buffer = &(kernel->machine->mainMemory[val]);
size = SysWrite(buffer, size, fd);
kernel->machine->WriteRegister(2, (int)size);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Close:
fd = kernel->machine->ReadRegister(4);
{
val = SysClose(fd);
kernel->machine->WriteRegister(2, (int)val);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Read:
val = kernel->machine->ReadRegister(4);
size = kernel->machine->ReadRegister(5);
fd = kernel->machine->ReadRegister(6);
{
char* buffer = &(kernel->machine->mainMemory[val]);
size = SysRead(buffer, size, fd);
kernel->machine->WriteRegister(2, (int)size);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Add:
DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n");
/* Process SysAdd Systemcall*/
@@ -118,92 +182,6 @@ ExceptionHandler(ExceptionType which)
cout << "return value:" << val << endl;
kernel->currentThread->Finish();
break;
case SC_PrintInt:
DEBUG(dbgAddr, "Printing int\n");
val = (int)kernel->machine->ReadRegister(4);
SysPrintInt(val);
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Open:
DEBUG(dbgAddr, "Open file\n");
{
val = kernel->machine->ReadRegister(4);
char *name = &(kernel->machine->mainMemory[val]);
OpenFileId ret = SysOpen(name);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Read:
DEBUG(dbgAddr, "Read file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
int ret = SysRead(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Write:
DEBUG(dbgAddr, "Write file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
// fprintf(stderr, "buffer: %p\n", buffer);
// cerr << "size: " << size << endl;
// cerr << "id: " << id << endl;
int ret = SysWrite(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Close:
DEBUG(dbgAddr, "Close file\n");
{
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(4);
int ret = SysClose(id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
default:
cerr << "Unexpected system call " << type << "\n";
break;

View File

@@ -0,0 +1,11 @@
#include "syscall.h"
int
main()
{
int n;
for (n = 0; n < 4; n++) {
PrintInt(1);
}
return 0;
}

View File

@@ -0,0 +1,11 @@
#include "syscall.h"
int
main()
{
int n;
for (n = 0; n < 5; n++) {
PrintInt(2);
}
return 0;
}

View File

@@ -0,0 +1,12 @@
#include "syscall.h"
int
main()
{
int n;
for (n = 0; n < 12; n++) {
PrintInt(3);
}
return 0;
}

View File

@@ -0,0 +1,12 @@
#include "syscall.h"
int
main()
{
int n;
for (n = 0; n < 11; n++) {
PrintInt(4);
}
return 0;
}

View File

@@ -11,12 +11,11 @@
#ifndef __USERPROG_KSYSCALL_H__
#define __USERPROG_KSYSCALL_H__
#define INT_BUF_LENGTH 13
#include "kernel.h"
#include "synchconsole.h"
typedef int OpenFileId;
void SysHalt()
{
@@ -36,43 +35,37 @@ int SysCreate(char *filename)
return kernel->interrupt->CreateFile(filename);
}
void SysPrintInt(int value) {
void SysPrintInt(int value)
{
kernel->interrupt->PrintInt(value);
}
OpenFileId SysOpen(char *name) {
OpenFileId id = -1;
for (int i = 0; i < 20; i++)
if (kernel->fileSystem->fileDescriptorTable[i] == NULL) {
id = i;
kernel->fileSystem->fileDescriptorTable[i]
= kernel->fileSystem->Open(name);
if (kernel->fileSystem->fileDescriptorTable[i] == NULL)
return -1;
break;
}
return id;
// -1: open fail
// fd
OpenFileId SysOpen(char* filename)
{
return kernel->interrupt->OpenFile(filename);
}
int SysWrite(char *buffer, int size, OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return -1;
return kernel->fileSystem->fileDescriptorTable[id]->Write(buffer, size);
// -1: write fail
// size
int SysWrite(char* buffer, int size, OpenFileId fd)
{
return kernel->interrupt->WriteFile(buffer, size, fd);
}
int SysRead(char *buffer, int size, OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return -1;
return kernel->fileSystem->fileDescriptorTable[id]->Read(buffer, size);
// 1: close success
// 0: close fail
int SysClose(OpenFileId fd)
{
return kernel->interrupt->CloseFile(fd);
}
int SysClose(OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return 0;
delete kernel->fileSystem->fileDescriptorTable[id];
kernel->fileSystem->fileDescriptorTable[id] = NULL;
return 1;
// -1: read fail
// size
int SysRead(char* buffer, int size, OpenFileId fd)
{
return kernel->interrupt->ReadFile(buffer, size, fd);
}
#endif /* ! __USERPROG_KSYSCALL_H__ */

View File

@@ -6,8 +6,7 @@
*/
#define NOFFMAGIC 0xbadfad /* magic number denoting Nachos
* object code file
*/
/* object code file*/
typedef struct segment {
int virtualAddr; /* location of segment in virt addr space */

View File

@@ -106,6 +106,11 @@ SynchConsoleOutput::PutChar(char ch)
lock->Release();
}
//----------------------------------------------------------------------
// SynchConsoleOutput::PutInt
// Write a int to the console display, waiting if necessary.
//----------------------------------------------------------------------
void
SynchConsoleOutput::PutInt(int value)
{

View File

@@ -34,11 +34,9 @@
#define SC_ExecV 13
#define SC_ThreadExit 14
#define SC_ThreadJoin 15
#define SC_PrintInt 16
#define SC_Add 42
#define SC_MSG 100
#define SC_PrintInt 16
#ifndef IN_ASM
@@ -55,6 +53,11 @@
/* Stop Nachos, and print out performance stats */
void Halt();
/*
* Show the int value on console
*/
void PrintInt(int value);
/*
* Add the two operants and return the result
*/
@@ -180,8 +183,6 @@ int ThreadJoin(ThreadId id);
*/
void ThreadExit(int ExitCode);
void PrintInt(int number);
#endif /* IN_ASM */
#endif /* SYSCALL_H */

View File

@@ -2,6 +2,6 @@
services:
test:
build: .
user: '60139:60139'
user: ytshih
volumes:
- './:/work'