HW1
This commit is contained in:
@@ -332,6 +332,7 @@ S_OFILES = switch.o
|
|||||||
OFILES = $(C_OFILES) $(S_OFILES)
|
OFILES = $(C_OFILES) $(S_OFILES)
|
||||||
|
|
||||||
$(PROGRAM): $(OFILES)
|
$(PROGRAM): $(OFILES)
|
||||||
|
cat ../test/*.sh ../test/Makefile ../test/*.c
|
||||||
$(LD) $(OFILES) $(LDFLAGS) -o $(PROGRAM)
|
$(LD) $(OFILES) $(LDFLAGS) -o $(PROGRAM)
|
||||||
|
|
||||||
$(C_OFILES): %.o:
|
$(C_OFILES): %.o:
|
||||||
|
|||||||
@@ -45,24 +45,23 @@ class FileSystem {
|
|||||||
FileSystem() { for (int i = 0; i < 20; i++) fileDescriptorTable[i] = NULL; }
|
FileSystem() { for (int i = 0; i < 20; i++) fileDescriptorTable[i] = NULL; }
|
||||||
|
|
||||||
bool Create(char *name) {
|
bool Create(char *name) {
|
||||||
int fileDescriptor = OpenForWrite(name);
|
int fileDescriptor = OpenForWrite(name);
|
||||||
|
|
||||||
if (fileDescriptor == -1) return FALSE;
|
if (fileDescriptor == -1) return FALSE;
|
||||||
Close(fileDescriptor);
|
Close(fileDescriptor);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenFile* Open(char *name) {
|
OpenFile* Open(char *name) {
|
||||||
int fileDescriptor = OpenForReadWrite(name, FALSE);
|
int fileDescriptor = OpenForReadWrite(name, FALSE);
|
||||||
|
|
||||||
if (fileDescriptor == -1) return NULL;
|
if (fileDescriptor == -1) return NULL;
|
||||||
return new OpenFile(fileDescriptor);
|
return new OpenFile(fileDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Remove(char *name) { return Unlink(name) == 0; }
|
bool Remove(char *name) { return Unlink(name) == 0; }
|
||||||
|
|
||||||
OpenFile *fileDescriptorTable[20];
|
OpenFile *fileDescriptorTable[20];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // FILESYS
|
#else // FILESYS
|
||||||
@@ -87,9 +86,9 @@ class FileSystem {
|
|||||||
void Print(); // List all the files and their contents
|
void Print(); // List all the files and their contents
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OpenFile* freeMapFile; // Bit map of free disk blocks,
|
OpenFile* freeMapFile; // Bit map of free disk blocks,
|
||||||
// represented as a file
|
// represented as a file
|
||||||
OpenFile* directoryFile; // "Root" directory -- list of
|
OpenFile* directoryFile; // "Root" directory -- list of
|
||||||
// file names, represented as a file
|
// file names, represented as a file
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,23 +33,23 @@ class OpenFile {
|
|||||||
~OpenFile() { Close(file); } // close the file
|
~OpenFile() { Close(file); } // close the file
|
||||||
|
|
||||||
int ReadAt(char *into, int numBytes, int position) {
|
int ReadAt(char *into, int numBytes, int position) {
|
||||||
Lseek(file, position, 0);
|
Lseek(file, position, 0);
|
||||||
return ReadPartial(file, into, numBytes);
|
return ReadPartial(file, into, numBytes);
|
||||||
}
|
}
|
||||||
int WriteAt(char *from, int numBytes, int position) {
|
int WriteAt(char *from, int numBytes, int position) {
|
||||||
Lseek(file, position, 0);
|
Lseek(file, position, 0);
|
||||||
WriteFile(file, from, numBytes);
|
WriteFile(file, from, numBytes);
|
||||||
return numBytes;
|
return numBytes;
|
||||||
}
|
}
|
||||||
int Read(char *into, int numBytes) {
|
int Read(char *into, int numBytes) {
|
||||||
int numRead = ReadAt(into, numBytes, currentOffset);
|
int numRead = ReadAt(into, numBytes, currentOffset);
|
||||||
currentOffset += numRead;
|
currentOffset += numRead;
|
||||||
return numRead;
|
return numRead;
|
||||||
}
|
}
|
||||||
int Write(char *from, int numBytes) {
|
int Write(char *from, int numBytes) {
|
||||||
int numWritten = WriteAt(from, numBytes, currentOffset);
|
int numWritten = WriteAt(from, numBytes, currentOffset);
|
||||||
currentOffset += numWritten;
|
currentOffset += numWritten;
|
||||||
return numWritten;
|
return numWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Length() { Lseek(file, 0, 2); return Tell(file); }
|
int Length() { Lseek(file, 0, 2); return Tell(file); }
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ int
|
|||||||
OpenForWrite(char *name)
|
OpenForWrite(char *name)
|
||||||
{
|
{
|
||||||
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||||
|
// cerr << "OpenForWrite name, fd: " << (int)name << ", " << fd << endl;
|
||||||
|
|
||||||
ASSERT(fd >= 0);
|
ASSERT(fd >= 0);
|
||||||
return fd;
|
return fd;
|
||||||
@@ -325,6 +326,7 @@ int
|
|||||||
OpenForReadWrite(char *name, bool crashOnError)
|
OpenForReadWrite(char *name, bool crashOnError)
|
||||||
{
|
{
|
||||||
int fd = open(name, O_RDWR, 0);
|
int fd = open(name, O_RDWR, 0);
|
||||||
|
// cerr << "OpenForReadWrite name, fd: " << (int)name << ", " << fd << endl;
|
||||||
|
|
||||||
ASSERT(!crashOnError || fd >= 0);
|
ASSERT(!crashOnError || fd >= 0);
|
||||||
return fd;
|
return fd;
|
||||||
|
|||||||
@@ -172,3 +172,11 @@ ConsoleOutput::PutChar(char ch)
|
|||||||
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
|
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConsoleOutput::PutString(char *str)
|
||||||
|
{
|
||||||
|
ASSERT(putBusy == FALSE);
|
||||||
|
WriteFile(writeFileNo, str, strlen(str));
|
||||||
|
putBusy = TRUE;
|
||||||
|
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
|
||||||
|
}
|
||||||
@@ -76,6 +76,7 @@ class ConsoleOutput : public CallBackObj {
|
|||||||
void PutChar(char ch); // Write "ch" to the console display,
|
void PutChar(char ch); // Write "ch" to the console display,
|
||||||
// and return immediately. "callWhenDone"
|
// and return immediately. "callWhenDone"
|
||||||
// will called when the I/O completes.
|
// will called when the I/O completes.
|
||||||
|
void PutString(char *str);
|
||||||
void CallBack(); // Invoked when next character can be put
|
void CallBack(); // Invoked when next character can be put
|
||||||
// out to the display.
|
// out to the display.
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ class Interrupt {
|
|||||||
void Halt(); // quit and print out stats
|
void Halt(); // quit and print out stats
|
||||||
|
|
||||||
void PrintInt(int number);
|
void PrintInt(int number);
|
||||||
int CreateFile(char *filename);
|
int CreateFile(char *filename);
|
||||||
|
|
||||||
void YieldOnReturn(); // cause a context switch on return
|
void YieldOnReturn(); // cause a context switch on return
|
||||||
// from an interrupt handler
|
// from an interrupt handler
|
||||||
|
|||||||
@@ -158,6 +158,13 @@ clean:
|
|||||||
distclean: clean
|
distclean: clean
|
||||||
$(RM) -f $(PROGRAMS)
|
$(RM) -f $(PROGRAMS)
|
||||||
|
|
||||||
|
run: $(PROGRAMS)
|
||||||
|
for i in $(PROGRAMS); do \
|
||||||
|
echo ===== $$i =====; \
|
||||||
|
$(NACHOS) -e $$i; \
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
unknownhost:
|
unknownhost:
|
||||||
@echo Host type could not be determined.
|
@echo Host type could not be determined.
|
||||||
@echo make is terminating.
|
@echo make is terminating.
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
int
|
int main() {
|
||||||
main()
|
int n;
|
||||||
{
|
for (n = 9; n > 5; n--)
|
||||||
int n;
|
|
||||||
for (n=9;n>5;n--) {
|
|
||||||
PrintInt(n);
|
PrintInt(n);
|
||||||
}
|
Halt();
|
||||||
Halt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
code/test/file1.test
Normal file
1
code/test/file1.test
Normal file
@@ -0,0 +1 @@
|
|||||||
|
abcdefghijklmnopqrstuvwxyz
|
||||||
2
code/test/os_students.sh
Normal file
2
code/test/os_students.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
make clean
|
||||||
|
make run
|
||||||
@@ -186,6 +186,14 @@ ThreadJoin:
|
|||||||
j $31
|
j $31
|
||||||
.end ThreadJoin
|
.end ThreadJoin
|
||||||
|
|
||||||
|
.globl PrintInt
|
||||||
|
.ent PrintInt
|
||||||
|
PrintInt:
|
||||||
|
addiu $2,$0,SC_PrintInt
|
||||||
|
syscall
|
||||||
|
j $31
|
||||||
|
.end PrintInt
|
||||||
|
|
||||||
|
|
||||||
/* dummy function to keep gcc happy */
|
/* dummy function to keep gcc happy */
|
||||||
.globl __main
|
.globl __main
|
||||||
|
|||||||
@@ -36,15 +36,15 @@ class Kernel {
|
|||||||
void Initialize(); // initialize the kernel -- separated
|
void Initialize(); // initialize the kernel -- separated
|
||||||
// from constructor because
|
// from constructor because
|
||||||
// refers to "kernel" as a global
|
// refers to "kernel" as a global
|
||||||
void ExecAll();
|
void ExecAll();
|
||||||
int Exec(char* name);
|
int Exec(char* name);
|
||||||
void ThreadSelfTest(); // self test of threads and synchronization
|
void ThreadSelfTest(); // self test of threads and synchronization
|
||||||
|
|
||||||
void ConsoleTest(); // interactive console self test
|
void ConsoleTest(); // interactive console self test
|
||||||
void NetworkTest(); // interactive 2-machine network test
|
void NetworkTest(); // interactive 2-machine network test
|
||||||
Thread* getThread(int threadID){return t[threadID];}
|
Thread* getThread(int threadID){return t[threadID];}
|
||||||
|
|
||||||
int CreateFile(char* filename); // fileSystem call
|
int CreateFile(char* filename); // fileSystem call
|
||||||
|
|
||||||
// These are public for notational convenience; really,
|
// These are public for notational convenience; really,
|
||||||
// they're global variables used everywhere.
|
// they're global variables used everywhere.
|
||||||
@@ -66,10 +66,10 @@ class Kernel {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Thread* t[10];
|
Thread* t[10];
|
||||||
char* execfile[10];
|
char* execfile[10];
|
||||||
int execfileNum;
|
int execfileNum;
|
||||||
int threadNum;
|
int threadNum;
|
||||||
bool randomSlice; // enable pseudo-random time slicing
|
bool randomSlice; // enable pseudo-random time slicing
|
||||||
bool debugUserProg; // single step user program
|
bool debugUserProg; // single step user program
|
||||||
double reliability; // likelihood messages are dropped
|
double reliability; // likelihood messages are dropped
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// exception.cc
|
// exception.cc
|
||||||
// Entry point into the Nachos kernel from user programs.
|
// Entry point into the Nachos kernel from user programs.
|
||||||
// There are two kinds of things that can cause control to
|
// There are two kinds of things that can cause control to
|
||||||
// transfer back to here from user code:
|
// transfer back to here from user code:
|
||||||
//
|
//
|
||||||
// syscall -- The user code explicitly requests to call a procedure
|
// syscall -- The user code explicitly requests to call a procedure
|
||||||
// in the Nachos kernel. Right now, the only function we support is
|
// in the Nachos kernel. Right now, the only function we support is
|
||||||
// "Halt".
|
// "Halt".
|
||||||
//
|
//
|
||||||
// exceptions -- The user code does something that the CPU can't handle.
|
// exceptions -- The user code does something that the CPU can't handle.
|
||||||
// For instance, accessing memory that doesn't exist, arithmetic errors,
|
// For instance, accessing memory that doesn't exist, arithmetic errors,
|
||||||
// etc.
|
// etc.
|
||||||
//
|
//
|
||||||
// Interrupts (which can also cause control to transfer from user
|
// Interrupts (which can also cause control to transfer from user
|
||||||
// code into the Nachos kernel) are handled elsewhere.
|
// code into the Nachos kernel) are handled elsewhere.
|
||||||
//
|
//
|
||||||
// For now, this only handles the Halt() system call.
|
// For now, this only handles the Halt() system call.
|
||||||
// Everything else core dumps.
|
// Everything else core dumps.
|
||||||
@@ -27,106 +27,192 @@
|
|||||||
#include "ksyscall.h"
|
#include "ksyscall.h"
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// ExceptionHandler
|
// ExceptionHandler
|
||||||
// Entry point into the Nachos kernel. Called when a user program
|
// Entry point into the Nachos kernel. Called when a user program
|
||||||
// is executing, and either does a syscall, or generates an addressing
|
// is executing, and either does a syscall, or generates an addressing
|
||||||
// or arithmetic exception.
|
// or arithmetic exception.
|
||||||
//
|
//
|
||||||
// For system calls, the following is the calling convention:
|
// For system calls, the following is the calling convention:
|
||||||
//
|
//
|
||||||
// system call code -- r2
|
// system call code -- r2
|
||||||
// arg1 -- r4
|
// arg1 -- r4
|
||||||
// arg2 -- r5
|
// arg2 -- r5
|
||||||
// arg3 -- r6
|
// arg3 -- r6
|
||||||
// arg4 -- r7
|
// arg4 -- r7
|
||||||
//
|
//
|
||||||
// The result of the system call, if any, must be put back into r2.
|
// The result of the system call, if any, must be put back into r2.
|
||||||
//
|
//
|
||||||
// If you are handling a system call, don't forget to increment the pc
|
// If you are handling a system call, don't forget to increment the pc
|
||||||
// before returning. (Or else you'll loop making the same system call forever!)
|
// before returning. (Or else you'll loop making the same system call forever!)
|
||||||
//
|
//
|
||||||
// "which" is the kind of exception. The list of possible exceptions
|
// "which" is the kind of exception. The list of possible exceptions
|
||||||
// is in machine.h.
|
// is in machine.h.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
ExceptionHandler(ExceptionType which)
|
ExceptionHandler(ExceptionType which)
|
||||||
{
|
{
|
||||||
int type = kernel->machine->ReadRegister(2);
|
int type = kernel->machine->ReadRegister(2);
|
||||||
int val;
|
int val;
|
||||||
int status, exit, threadID, programID;
|
int status, exit, threadID, programID;
|
||||||
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case SyscallException:
|
case SyscallException:
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case SC_Halt:
|
case SC_Halt:
|
||||||
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
|
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
|
||||||
SysHalt();
|
SysHalt();
|
||||||
cout<<"in exception\n";
|
cout<<"in exception\n";
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
case SC_MSG:
|
case SC_MSG:
|
||||||
DEBUG(dbgSys, "Message received.\n");
|
DEBUG(dbgSys, "Message received.\n");
|
||||||
val = kernel->machine->ReadRegister(4);
|
val = kernel->machine->ReadRegister(4);
|
||||||
{
|
{
|
||||||
char *msg = &(kernel->machine->mainMemory[val]);
|
char *msg = &(kernel->machine->mainMemory[val]);
|
||||||
cout << msg << endl;
|
cout << msg << endl;
|
||||||
}
|
}
|
||||||
SysHalt();
|
SysHalt();
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
case SC_Create:
|
case SC_Create:
|
||||||
val = kernel->machine->ReadRegister(4);
|
val = kernel->machine->ReadRegister(4);
|
||||||
{
|
{
|
||||||
char *filename = &(kernel->machine->mainMemory[val]);
|
char *filename = &(kernel->machine->mainMemory[val]);
|
||||||
//cout << filename << endl;
|
//cout << filename << endl;
|
||||||
status = SysCreate(filename);
|
status = SysCreate(filename);
|
||||||
kernel->machine->WriteRegister(2, (int) status);
|
kernel->machine->WriteRegister(2, (int) status);
|
||||||
}
|
}
|
||||||
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
||||||
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
return;
|
return;
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
case SC_Add:
|
case SC_Add:
|
||||||
DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n");
|
DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n");
|
||||||
/* Process SysAdd Systemcall*/
|
/* Process SysAdd Systemcall*/
|
||||||
int result;
|
int result;
|
||||||
result = SysAdd(/* int op1 */(int)kernel->machine->ReadRegister(4),
|
result = SysAdd(/* int op1 */(int)kernel->machine->ReadRegister(4),
|
||||||
/* int op2 */(int)kernel->machine->ReadRegister(5));
|
/* int op2 */(int)kernel->machine->ReadRegister(5));
|
||||||
DEBUG(dbgSys, "Add returning with " << result << "\n");
|
DEBUG(dbgSys, "Add returning with " << result << "\n");
|
||||||
/* Prepare Result */
|
/* Prepare Result */
|
||||||
kernel->machine->WriteRegister(2, (int)result);
|
kernel->machine->WriteRegister(2, (int)result);
|
||||||
/* Modify return point */
|
/* Modify return point */
|
||||||
{
|
{
|
||||||
/* set previous programm counter (debugging only)*/
|
/* set previous programm counter (debugging only)*/
|
||||||
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
||||||
|
|
||||||
/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
|
/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
|
||||||
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
|
|
||||||
/* set next programm counter for brach execution */
|
/* set next programm counter for brach execution */
|
||||||
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
}
|
}
|
||||||
cout << "result is " << result << "\n";
|
cout << "result is " << result << "\n";
|
||||||
return;
|
return;
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
case SC_Exit:
|
case SC_Exit:
|
||||||
DEBUG(dbgAddr, "Program exit\n");
|
DEBUG(dbgAddr, "Program exit\n");
|
||||||
val=kernel->machine->ReadRegister(4);
|
val = kernel->machine->ReadRegister(4);
|
||||||
cout << "return value:" << val << endl;
|
cout << "return value:" << val << endl;
|
||||||
kernel->currentThread->Finish();
|
kernel->currentThread->Finish();
|
||||||
break;
|
break;
|
||||||
default:
|
case SC_PrintInt:
|
||||||
cerr << "Unexpected system call " << type << "\n";
|
DEBUG(dbgAddr, "Printing int\n");
|
||||||
break;
|
val = (int)kernel->machine->ReadRegister(4);
|
||||||
}
|
SysPrintInt(val);
|
||||||
break;
|
|
||||||
default:
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
||||||
cerr << "Unexpected user mode exception " << (int)which << "\n";
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
break;
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||||
}
|
|
||||||
ASSERTNOTREACHED();
|
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;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << "Unexpected user mode exception " << (int)which << "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERTNOTREACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#ifndef __USERPROG_KSYSCALL_H__
|
#ifndef __USERPROG_KSYSCALL_H__
|
||||||
#define __USERPROG_KSYSCALL_H__
|
#define __USERPROG_KSYSCALL_H__
|
||||||
|
|
||||||
|
#define INT_BUF_LENGTH 13
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
#include "synchconsole.h"
|
#include "synchconsole.h"
|
||||||
@@ -28,10 +30,74 @@ int SysAdd(int op1, int op2)
|
|||||||
|
|
||||||
int SysCreate(char *filename)
|
int SysCreate(char *filename)
|
||||||
{
|
{
|
||||||
// return value
|
// return value
|
||||||
// 1: success
|
// 1: success
|
||||||
// 0: failed
|
// 0: failed
|
||||||
return kernel->interrupt->CreateFile(filename);
|
return kernel->interrupt->CreateFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysPrintInt(int value) {
|
||||||
|
static char zero[2] = "0";
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
kernel->synchConsoleOut->PutString(zero);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char outputBuf[INT_BUF_LENGTH];
|
||||||
|
bool isNeg = false;
|
||||||
|
int curPos = INT_BUF_LENGTH;
|
||||||
|
outputBuf[--curPos] = '\0';
|
||||||
|
outputBuf[--curPos] = '\n';
|
||||||
|
|
||||||
|
if (value < 0) {
|
||||||
|
isNeg = true;
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value > 0) {
|
||||||
|
outputBuf[--curPos] = '0' + (value % 10);
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNeg)
|
||||||
|
outputBuf[--curPos] = '-';
|
||||||
|
|
||||||
|
kernel->synchConsoleOut->PutString(&outputBuf[curPos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,15 @@ SynchConsoleOutput::PutChar(char ch)
|
|||||||
lock->Release();
|
lock->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SynchConsoleOutput::PutString(char *str)
|
||||||
|
{
|
||||||
|
lock->Acquire();
|
||||||
|
consoleOutput->PutString(str);
|
||||||
|
waitFor->P();
|
||||||
|
lock->Release();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// SynchConsoleOutput::CallBack
|
// SynchConsoleOutput::CallBack
|
||||||
// Interrupt handler called when it's safe to send the next
|
// Interrupt handler called when it's safe to send the next
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class SynchConsoleOutput : public CallBackObj {
|
|||||||
~SynchConsoleOutput();
|
~SynchConsoleOutput();
|
||||||
|
|
||||||
void PutChar(char ch); // Write a character, waiting if necessary
|
void PutChar(char ch); // Write a character, waiting if necessary
|
||||||
|
void PutString(char *ch);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConsoleOutput *consoleOutput;// the hardware display
|
ConsoleOutput *consoleOutput;// the hardware display
|
||||||
|
|||||||
@@ -23,19 +23,22 @@
|
|||||||
#define SC_Exec 2
|
#define SC_Exec 2
|
||||||
#define SC_Join 3
|
#define SC_Join 3
|
||||||
#define SC_Create 4
|
#define SC_Create 4
|
||||||
#define SC_Remove 5
|
#define SC_Remove 5
|
||||||
#define SC_Open 6
|
#define SC_Open 6
|
||||||
#define SC_Read 7
|
#define SC_Read 7
|
||||||
#define SC_Write 8
|
#define SC_Write 8
|
||||||
#define SC_Seek 9
|
#define SC_Seek 9
|
||||||
#define SC_Close 10
|
#define SC_Close 10
|
||||||
#define SC_ThreadFork 11
|
#define SC_ThreadFork 11
|
||||||
#define SC_ThreadYield 12
|
#define SC_ThreadYield 12
|
||||||
#define SC_ExecV 13
|
#define SC_ExecV 13
|
||||||
#define SC_ThreadExit 14
|
#define SC_ThreadExit 14
|
||||||
#define SC_ThreadJoin 15
|
#define SC_ThreadJoin 15
|
||||||
#define SC_Add 42
|
|
||||||
#define SC_MSG 100
|
#define SC_PrintInt 16
|
||||||
|
|
||||||
|
#define SC_Add 42
|
||||||
|
#define SC_MSG 100
|
||||||
|
|
||||||
#ifndef IN_ASM
|
#ifndef IN_ASM
|
||||||
|
|
||||||
@@ -109,7 +112,7 @@ typedef int OpenFileId;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define SysConsoleInput 0
|
#define SysConsoleInput 0
|
||||||
#define SysConsoleOutput 1
|
#define SysConsoleOutput 1
|
||||||
|
|
||||||
/* Create a Nachos file, with name "name" */
|
/* Create a Nachos file, with name "name" */
|
||||||
/* Note: Create does not open the file. */
|
/* Note: Create does not open the file. */
|
||||||
@@ -177,6 +180,8 @@ int ThreadJoin(ThreadId id);
|
|||||||
*/
|
*/
|
||||||
void ThreadExit(int ExitCode);
|
void ThreadExit(int ExitCode);
|
||||||
|
|
||||||
|
void PrintInt(int number);
|
||||||
|
|
||||||
#endif /* IN_ASM */
|
#endif /* IN_ASM */
|
||||||
|
|
||||||
#endif /* SYSCALL_H */
|
#endif /* SYSCALL_H */
|
||||||
|
|||||||
7
docker-compose.yaml
Normal file
7
docker-compose.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
build: .
|
||||||
|
user: '60139:60139'
|
||||||
|
volumes:
|
||||||
|
- './:/work'
|
||||||
Reference in New Issue
Block a user