Merge branch 'ytshih-hw1' into 'main'
HW1 See merge request cs_os_group_20/cs_os_project_20_hw!1
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.o
|
||||
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
RUN dpkg --add-architecture i386
|
||||
RUN apt-get update && apt-get dist-upgrade
|
||||
RUN apt-get -y install build-essential ed \
|
||||
gcc-multilib g++-multilib lib32ncurses5-dev lib32z1 \
|
||||
zlib1g:i386 libstdc++6:i386 libc6:i386 libncurses5:i386 \
|
||||
libgcc1:i386 libstdc++5:i386
|
||||
RUN groupadd -g 60139 ytshih && useradd -g 60139 -u 60139 ytshih
|
||||
|
||||
WORKDIR /work
|
||||
ENTRYPOINT ["/usr/bin/env"]
|
||||
CMD ["bash"]
|
||||
14
code/Makefile
Normal file
14
code/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
.PHONY: all clean run
|
||||
|
||||
all:
|
||||
make -C build.linux depend
|
||||
make -C build.linux
|
||||
make -C test
|
||||
|
||||
clean:
|
||||
make -C build.linux clean
|
||||
make -C test distclean
|
||||
|
||||
run:
|
||||
make -C test run
|
||||
@@ -332,6 +332,7 @@ 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:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -45,24 +45,23 @@ class FileSystem {
|
||||
FileSystem() { for (int i = 0; i < 20; i++) fileDescriptorTable[i] = NULL; }
|
||||
|
||||
bool Create(char *name) {
|
||||
int fileDescriptor = OpenForWrite(name);
|
||||
int fileDescriptor = OpenForWrite(name);
|
||||
|
||||
if (fileDescriptor == -1) return FALSE;
|
||||
Close(fileDescriptor);
|
||||
return TRUE;
|
||||
}
|
||||
if (fileDescriptor == -1) return FALSE;
|
||||
Close(fileDescriptor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
OpenFile* Open(char *name) {
|
||||
int fileDescriptor = OpenForReadWrite(name, FALSE);
|
||||
int fileDescriptor = OpenForReadWrite(name, FALSE);
|
||||
|
||||
if (fileDescriptor == -1) return NULL;
|
||||
return new OpenFile(fileDescriptor);
|
||||
}
|
||||
if (fileDescriptor == -1) return NULL;
|
||||
return new OpenFile(fileDescriptor);
|
||||
}
|
||||
|
||||
bool Remove(char *name) { return Unlink(name) == 0; }
|
||||
|
||||
OpenFile *fileDescriptorTable[20];
|
||||
|
||||
OpenFile *fileDescriptorTable[20];
|
||||
};
|
||||
|
||||
#else // FILESYS
|
||||
@@ -87,9 +86,9 @@ class FileSystem {
|
||||
void Print(); // List all the files and their contents
|
||||
|
||||
private:
|
||||
OpenFile* freeMapFile; // Bit map of free disk blocks,
|
||||
OpenFile* freeMapFile; // Bit map of free disk blocks,
|
||||
// represented as a file
|
||||
OpenFile* directoryFile; // "Root" directory -- list of
|
||||
OpenFile* directoryFile; // "Root" directory -- list of
|
||||
// file names, represented as a file
|
||||
};
|
||||
|
||||
|
||||
@@ -33,23 +33,23 @@ class OpenFile {
|
||||
~OpenFile() { Close(file); } // close the file
|
||||
|
||||
int ReadAt(char *into, int numBytes, int position) {
|
||||
Lseek(file, position, 0);
|
||||
return ReadPartial(file, into, numBytes);
|
||||
Lseek(file, position, 0);
|
||||
return ReadPartial(file, into, numBytes);
|
||||
}
|
||||
int WriteAt(char *from, int numBytes, int position) {
|
||||
Lseek(file, position, 0);
|
||||
WriteFile(file, from, numBytes);
|
||||
return numBytes;
|
||||
Lseek(file, position, 0);
|
||||
WriteFile(file, from, numBytes);
|
||||
return numBytes;
|
||||
}
|
||||
int Read(char *into, int numBytes) {
|
||||
int numRead = ReadAt(into, numBytes, currentOffset);
|
||||
currentOffset += numRead;
|
||||
return numRead;
|
||||
}
|
||||
int numRead = ReadAt(into, numBytes, currentOffset);
|
||||
currentOffset += numRead;
|
||||
return numRead;
|
||||
}
|
||||
int Write(char *from, int numBytes) {
|
||||
int numWritten = WriteAt(from, numBytes, currentOffset);
|
||||
currentOffset += numWritten;
|
||||
return numWritten;
|
||||
int numWritten = WriteAt(from, numBytes, currentOffset);
|
||||
currentOffset += numWritten;
|
||||
return numWritten;
|
||||
}
|
||||
|
||||
int Length() { Lseek(file, 0, 2); return Tell(file); }
|
||||
|
||||
@@ -308,6 +308,7 @@ 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;
|
||||
@@ -325,6 +326,7 @@ 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;
|
||||
|
||||
@@ -172,3 +172,11 @@ ConsoleOutput::PutChar(char ch)
|
||||
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,
|
||||
// and return immediately. "callWhenDone"
|
||||
// will called when the I/O completes.
|
||||
void PutString(char *str);
|
||||
void CallBack(); // Invoked when next character can be put
|
||||
// out to the display.
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class Interrupt {
|
||||
void Halt(); // quit and print out stats
|
||||
|
||||
void PrintInt(int number);
|
||||
int CreateFile(char *filename);
|
||||
int CreateFile(char *filename);
|
||||
|
||||
void YieldOnReturn(); // cause a context switch on return
|
||||
// from an interrupt handler
|
||||
|
||||
@@ -107,13 +107,14 @@ LD = $(GCCDIR)ld
|
||||
|
||||
INCDIR =-I../userprog -I../lib
|
||||
CFLAGS = -G 0 -c $(INCDIR) -B../../usr/local/nachos/lib/gcc-lib/decstation-ultrix/2.95.2/ -B../../usr/local/nachos/decstation-ultrix/bin/
|
||||
NACHOS = ../build.linux/nachos
|
||||
|
||||
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
|
||||
PROGRAMS = halt
|
||||
PROGRAMS = add halt consoleIO_test1 consoleIO_test2 fileIO_test1 fileIO_test2
|
||||
# PROGRAMS = halt
|
||||
endif
|
||||
|
||||
all: $(PROGRAMS)
|
||||
@@ -196,6 +197,13 @@ clean:
|
||||
distclean: clean
|
||||
$(RM) -f $(PROGRAMS)
|
||||
|
||||
run: $(PROGRAMS)
|
||||
for i in $(PROGRAMS); do \
|
||||
echo ===== $$i =====; \
|
||||
$(NACHOS) -e $$i; \
|
||||
done
|
||||
|
||||
|
||||
unknownhost:
|
||||
@echo Host type could not be determined.
|
||||
@echo make is terminating.
|
||||
|
||||
BIN
code/test/add
BIN
code/test/add
Binary file not shown.
Binary file not shown.
@@ -1,12 +1,9 @@
|
||||
#include "syscall.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int n;
|
||||
for (n=9;n>5;n--) {
|
||||
int main() {
|
||||
int n;
|
||||
for (n = 9; n > 5; n--)
|
||||
PrintInt(n);
|
||||
}
|
||||
Halt();
|
||||
Halt();
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
1
code/test/file1.test
Normal file
1
code/test/file1.test
Normal file
@@ -0,0 +1 @@
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
Binary file not shown.
Binary file not shown.
BIN
code/test/halt
BIN
code/test/halt
Binary file not shown.
@@ -1,3 +1,2 @@
|
||||
make clean
|
||||
make -d
|
||||
../build.linux/nachos -e halt
|
||||
make run
|
||||
|
||||
@@ -186,6 +186,14 @@ 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
|
||||
|
||||
@@ -36,15 +36,15 @@ class Kernel {
|
||||
void Initialize(); // initialize the kernel -- separated
|
||||
// from constructor because
|
||||
// refers to "kernel" as a global
|
||||
void ExecAll();
|
||||
int Exec(char* name);
|
||||
void ExecAll();
|
||||
int Exec(char* name);
|
||||
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];}
|
||||
|
||||
int CreateFile(char* filename); // fileSystem call
|
||||
Thread* getThread(int threadID){return t[threadID];}
|
||||
|
||||
int CreateFile(char* filename); // fileSystem call
|
||||
|
||||
// These are public for notational convenience; really,
|
||||
// they're global variables used everywhere.
|
||||
@@ -66,10 +66,10 @@ class Kernel {
|
||||
|
||||
private:
|
||||
|
||||
Thread* t[10];
|
||||
char* execfile[10];
|
||||
int execfileNum;
|
||||
int threadNum;
|
||||
Thread* t[10];
|
||||
char* execfile[10];
|
||||
int execfileNum;
|
||||
int threadNum;
|
||||
bool randomSlice; // enable pseudo-random time slicing
|
||||
bool debugUserProg; // single step user program
|
||||
double reliability; // likelihood messages are dropped
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// exception.cc
|
||||
// Entry point into the Nachos kernel from user programs.
|
||||
// There are two kinds of things that can cause control to
|
||||
// transfer back to here from user code:
|
||||
// Entry point into the Nachos kernel from user programs.
|
||||
// There are two kinds of things that can cause control to
|
||||
// transfer back to here from user code:
|
||||
//
|
||||
// syscall -- The user code explicitly requests to call a procedure
|
||||
// in the Nachos kernel. Right now, the only function we support is
|
||||
// "Halt".
|
||||
// syscall -- The user code explicitly requests to call a procedure
|
||||
// in the Nachos kernel. Right now, the only function we support is
|
||||
// "Halt".
|
||||
//
|
||||
// exceptions -- The user code does something that the CPU can't handle.
|
||||
// For instance, accessing memory that doesn't exist, arithmetic errors,
|
||||
// etc.
|
||||
// exceptions -- The user code does something that the CPU can't handle.
|
||||
// For instance, accessing memory that doesn't exist, arithmetic errors,
|
||||
// etc.
|
||||
//
|
||||
// Interrupts (which can also cause control to transfer from user
|
||||
// code into the Nachos kernel) are handled elsewhere.
|
||||
// Interrupts (which can also cause control to transfer from user
|
||||
// code into the Nachos kernel) are handled elsewhere.
|
||||
//
|
||||
// For now, this only handles the Halt() system call.
|
||||
// Everything else core dumps.
|
||||
@@ -27,106 +27,192 @@
|
||||
#include "ksyscall.h"
|
||||
//----------------------------------------------------------------------
|
||||
// ExceptionHandler
|
||||
// Entry point into the Nachos kernel. Called when a user program
|
||||
// is executing, and either does a syscall, or generates an addressing
|
||||
// or arithmetic exception.
|
||||
// Entry point into the Nachos kernel. Called when a user program
|
||||
// is executing, and either does a syscall, or generates an addressing
|
||||
// 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
|
||||
// arg1 -- r4
|
||||
// arg2 -- r5
|
||||
// arg3 -- r6
|
||||
// arg4 -- r7
|
||||
// system call code -- r2
|
||||
// arg1 -- r4
|
||||
// arg2 -- r5
|
||||
// arg3 -- r6
|
||||
// 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
|
||||
// before returning. (Or else you'll loop making the same system call forever!)
|
||||
//
|
||||
// "which" is the kind of exception. The list of possible exceptions
|
||||
// is in machine.h.
|
||||
// "which" is the kind of exception. The list of possible exceptions
|
||||
// is in machine.h.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ExceptionHandler(ExceptionType which)
|
||||
{
|
||||
int type = kernel->machine->ReadRegister(2);
|
||||
int val;
|
||||
int status, exit, threadID, programID;
|
||||
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
||||
switch (which) {
|
||||
int type = kernel->machine->ReadRegister(2);
|
||||
int val;
|
||||
int status, exit, threadID, programID;
|
||||
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
||||
switch (which) {
|
||||
case SyscallException:
|
||||
switch(type) {
|
||||
case SC_Halt:
|
||||
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
|
||||
SysHalt();
|
||||
cout<<"in exception\n";
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_MSG:
|
||||
DEBUG(dbgSys, "Message received.\n");
|
||||
val = kernel->machine->ReadRegister(4);
|
||||
{
|
||||
char *msg = &(kernel->machine->mainMemory[val]);
|
||||
cout << msg << endl;
|
||||
}
|
||||
SysHalt();
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_Create:
|
||||
val = kernel->machine->ReadRegister(4);
|
||||
{
|
||||
char *filename = &(kernel->machine->mainMemory[val]);
|
||||
//cout << filename << endl;
|
||||
status = SysCreate(filename);
|
||||
kernel->machine->WriteRegister(2, (int) status);
|
||||
}
|
||||
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*/
|
||||
int result;
|
||||
result = SysAdd(/* int op1 */(int)kernel->machine->ReadRegister(4),
|
||||
/* int op2 */(int)kernel->machine->ReadRegister(5));
|
||||
DEBUG(dbgSys, "Add returning with " << result << "\n");
|
||||
/* Prepare Result */
|
||||
kernel->machine->WriteRegister(2, (int)result);
|
||||
/* Modify return point */
|
||||
{
|
||||
/* set previous programm counter (debugging only)*/
|
||||
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
||||
|
||||
/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
|
||||
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||
|
||||
/* set next programm counter for brach execution */
|
||||
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
|
||||
}
|
||||
cout << "result is " << result << "\n";
|
||||
return;
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_Exit:
|
||||
DEBUG(dbgAddr, "Program exit\n");
|
||||
val=kernel->machine->ReadRegister(4);
|
||||
cout << "return value:" << val << endl;
|
||||
kernel->currentThread->Finish();
|
||||
break;
|
||||
default:
|
||||
cerr << "Unexpected system call " << type << "\n";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << "Unexpected user mode exception " << (int)which << "\n";
|
||||
break;
|
||||
}
|
||||
ASSERTNOTREACHED();
|
||||
switch(type) {
|
||||
case SC_Halt:
|
||||
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
|
||||
SysHalt();
|
||||
cout<<"in exception\n";
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_MSG:
|
||||
DEBUG(dbgSys, "Message received.\n");
|
||||
val = kernel->machine->ReadRegister(4);
|
||||
{
|
||||
char *msg = &(kernel->machine->mainMemory[val]);
|
||||
cout << msg << endl;
|
||||
}
|
||||
SysHalt();
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_Create:
|
||||
val = kernel->machine->ReadRegister(4);
|
||||
{
|
||||
char *filename = &(kernel->machine->mainMemory[val]);
|
||||
//cout << filename << endl;
|
||||
status = SysCreate(filename);
|
||||
kernel->machine->WriteRegister(2, (int) status);
|
||||
}
|
||||
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*/
|
||||
int result;
|
||||
result = SysAdd(/* int op1 */(int)kernel->machine->ReadRegister(4),
|
||||
/* int op2 */(int)kernel->machine->ReadRegister(5));
|
||||
DEBUG(dbgSys, "Add returning with " << result << "\n");
|
||||
/* Prepare Result */
|
||||
kernel->machine->WriteRegister(2, (int)result);
|
||||
/* Modify return point */
|
||||
{
|
||||
/* set previous programm counter (debugging only)*/
|
||||
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
||||
|
||||
/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
|
||||
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||
|
||||
/* set next programm counter for brach execution */
|
||||
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
||||
}
|
||||
cout << "result is " << result << "\n";
|
||||
return;
|
||||
ASSERTNOTREACHED();
|
||||
break;
|
||||
case SC_Exit:
|
||||
DEBUG(dbgAddr, "Program exit\n");
|
||||
val = kernel->machine->ReadRegister(4);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << "Unexpected user mode exception " << (int)which << "\n";
|
||||
break;
|
||||
}
|
||||
ASSERTNOTREACHED();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,104 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* userprog/ksyscall.h
|
||||
*
|
||||
* Kernel interface for systemcalls
|
||||
*
|
||||
* by Marcus Voelp (c) Universitaet Karlsruhe
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
#ifndef __USERPROG_KSYSCALL_H__
|
||||
#define __USERPROG_KSYSCALL_H__
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#include "synchconsole.h"
|
||||
|
||||
|
||||
void SysHalt()
|
||||
{
|
||||
kernel->interrupt->Halt();
|
||||
}
|
||||
|
||||
int SysAdd(int op1, int op2)
|
||||
{
|
||||
return op1 + op2;
|
||||
}
|
||||
|
||||
int SysCreate(char *filename)
|
||||
{
|
||||
// return value
|
||||
// 1: success
|
||||
// 0: failed
|
||||
return kernel->interrupt->CreateFile(filename);
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
||||
/**************************************************************
|
||||
*
|
||||
* userprog/ksyscall.h
|
||||
*
|
||||
* Kernel interface for systemcalls
|
||||
*
|
||||
* by Marcus Voelp (c) Universitaet Karlsruhe
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
#ifndef __USERPROG_KSYSCALL_H__
|
||||
#define __USERPROG_KSYSCALL_H__
|
||||
|
||||
#define INT_BUF_LENGTH 13
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#include "synchconsole.h"
|
||||
|
||||
|
||||
void SysHalt()
|
||||
{
|
||||
kernel->interrupt->Halt();
|
||||
}
|
||||
|
||||
int SysAdd(int op1, int op2)
|
||||
{
|
||||
return op1 + op2;
|
||||
}
|
||||
|
||||
int SysCreate(char *filename)
|
||||
{
|
||||
// return value
|
||||
// 1: success
|
||||
// 0: failed
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
||||
|
||||
@@ -106,6 +106,15 @@ SynchConsoleOutput::PutChar(char ch)
|
||||
lock->Release();
|
||||
}
|
||||
|
||||
void
|
||||
SynchConsoleOutput::PutString(char *str)
|
||||
{
|
||||
lock->Acquire();
|
||||
consoleOutput->PutString(str);
|
||||
waitFor->P();
|
||||
lock->Release();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// SynchConsoleOutput::CallBack
|
||||
// Interrupt handler called when it's safe to send the next
|
||||
|
||||
@@ -41,6 +41,7 @@ class SynchConsoleOutput : public CallBackObj {
|
||||
~SynchConsoleOutput();
|
||||
|
||||
void PutChar(char ch); // Write a character, waiting if necessary
|
||||
void PutString(char *ch);
|
||||
|
||||
private:
|
||||
ConsoleOutput *consoleOutput;// the hardware display
|
||||
|
||||
@@ -23,19 +23,22 @@
|
||||
#define SC_Exec 2
|
||||
#define SC_Join 3
|
||||
#define SC_Create 4
|
||||
#define SC_Remove 5
|
||||
#define SC_Remove 5
|
||||
#define SC_Open 6
|
||||
#define SC_Read 7
|
||||
#define SC_Write 8
|
||||
#define SC_Seek 9
|
||||
#define SC_Close 10
|
||||
#define SC_ThreadFork 11
|
||||
#define SC_Seek 9
|
||||
#define SC_Close 10
|
||||
#define SC_ThreadFork 11
|
||||
#define SC_ThreadYield 12
|
||||
#define SC_ExecV 13
|
||||
#define SC_ExecV 13
|
||||
#define SC_ThreadExit 14
|
||||
#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
|
||||
|
||||
@@ -109,7 +112,7 @@ typedef int OpenFileId;
|
||||
*/
|
||||
|
||||
#define SysConsoleInput 0
|
||||
#define SysConsoleOutput 1
|
||||
#define SysConsoleOutput 1
|
||||
|
||||
/* Create a Nachos file, with name "name" */
|
||||
/* Note: Create does not open the file. */
|
||||
@@ -175,7 +178,9 @@ int ThreadJoin(ThreadId id);
|
||||
/*
|
||||
* Deletes current thread and returns ExitCode to every waiting lokal thread.
|
||||
*/
|
||||
void ThreadExit(int ExitCode);
|
||||
void ThreadExit(int ExitCode);
|
||||
|
||||
void PrintInt(int number);
|
||||
|
||||
#endif /* IN_ASM */
|
||||
|
||||
|
||||
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