diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1e426f8 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 0000000..16a83b4 --- /dev/null +++ b/code/Makefile @@ -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 diff --git a/code/build.linux/Makefile b/code/build.linux/Makefile index f17c497..e25b701 100644 --- a/code/build.linux/Makefile +++ b/code/build.linux/Makefile @@ -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: diff --git a/code/build.linux/addrspace.o b/code/build.linux/addrspace.o deleted file mode 100644 index 4c2c0ef..0000000 Binary files a/code/build.linux/addrspace.o and /dev/null differ diff --git a/code/build.linux/alarm.o b/code/build.linux/alarm.o deleted file mode 100644 index f6868cd..0000000 Binary files a/code/build.linux/alarm.o and /dev/null differ diff --git a/code/build.linux/bitmap.o b/code/build.linux/bitmap.o deleted file mode 100644 index 7a7517f..0000000 Binary files a/code/build.linux/bitmap.o and /dev/null differ diff --git a/code/build.linux/console.o b/code/build.linux/console.o deleted file mode 100644 index 4d2dda2..0000000 Binary files a/code/build.linux/console.o and /dev/null differ diff --git a/code/build.linux/debug.o b/code/build.linux/debug.o deleted file mode 100644 index dfd31ee..0000000 Binary files a/code/build.linux/debug.o and /dev/null differ diff --git a/code/build.linux/directory.o b/code/build.linux/directory.o deleted file mode 100644 index 5e04da4..0000000 Binary files a/code/build.linux/directory.o and /dev/null differ diff --git a/code/build.linux/disk.o b/code/build.linux/disk.o deleted file mode 100644 index 780b5a3..0000000 Binary files a/code/build.linux/disk.o and /dev/null differ diff --git a/code/build.linux/exception.o b/code/build.linux/exception.o deleted file mode 100644 index 57a3ccb..0000000 Binary files a/code/build.linux/exception.o and /dev/null differ diff --git a/code/build.linux/filehdr.o b/code/build.linux/filehdr.o deleted file mode 100644 index 14d889d..0000000 Binary files a/code/build.linux/filehdr.o and /dev/null differ diff --git a/code/build.linux/filesys.o b/code/build.linux/filesys.o deleted file mode 100644 index a47e761..0000000 Binary files a/code/build.linux/filesys.o and /dev/null differ diff --git a/code/build.linux/interrupt.o b/code/build.linux/interrupt.o deleted file mode 100644 index 422c1d2..0000000 Binary files a/code/build.linux/interrupt.o and /dev/null differ diff --git a/code/build.linux/kernel.o b/code/build.linux/kernel.o deleted file mode 100644 index 6a48a1e..0000000 Binary files a/code/build.linux/kernel.o and /dev/null differ diff --git a/code/build.linux/libtest.o b/code/build.linux/libtest.o deleted file mode 100644 index 7d7a361..0000000 Binary files a/code/build.linux/libtest.o and /dev/null differ diff --git a/code/build.linux/machine.o b/code/build.linux/machine.o deleted file mode 100644 index de70630..0000000 Binary files a/code/build.linux/machine.o and /dev/null differ diff --git a/code/build.linux/main.o b/code/build.linux/main.o deleted file mode 100644 index 6156015..0000000 Binary files a/code/build.linux/main.o and /dev/null differ diff --git a/code/build.linux/mipssim.o b/code/build.linux/mipssim.o deleted file mode 100644 index 93befd2..0000000 Binary files a/code/build.linux/mipssim.o and /dev/null differ diff --git a/code/build.linux/nachos b/code/build.linux/nachos index e60bbcc..e4314a0 100755 Binary files a/code/build.linux/nachos and b/code/build.linux/nachos differ diff --git a/code/build.linux/network.o b/code/build.linux/network.o deleted file mode 100644 index 7c83846..0000000 Binary files a/code/build.linux/network.o and /dev/null differ diff --git a/code/build.linux/openfile.o b/code/build.linux/openfile.o deleted file mode 100644 index 6dae252..0000000 Binary files a/code/build.linux/openfile.o and /dev/null differ diff --git a/code/build.linux/pbitmap.o b/code/build.linux/pbitmap.o deleted file mode 100644 index 32a5331..0000000 Binary files a/code/build.linux/pbitmap.o and /dev/null differ diff --git a/code/build.linux/post.o b/code/build.linux/post.o deleted file mode 100644 index 2d54399..0000000 Binary files a/code/build.linux/post.o and /dev/null differ diff --git a/code/build.linux/scheduler.o b/code/build.linux/scheduler.o deleted file mode 100644 index ccfd20c..0000000 Binary files a/code/build.linux/scheduler.o and /dev/null differ diff --git a/code/build.linux/stats.o b/code/build.linux/stats.o deleted file mode 100644 index fd0c04f..0000000 Binary files a/code/build.linux/stats.o and /dev/null differ diff --git a/code/build.linux/switch.o b/code/build.linux/switch.o deleted file mode 100644 index c29598a..0000000 Binary files a/code/build.linux/switch.o and /dev/null differ diff --git a/code/build.linux/synch.o b/code/build.linux/synch.o deleted file mode 100644 index 276fa60..0000000 Binary files a/code/build.linux/synch.o and /dev/null differ diff --git a/code/build.linux/synchconsole.o b/code/build.linux/synchconsole.o deleted file mode 100644 index b418d32..0000000 Binary files a/code/build.linux/synchconsole.o and /dev/null differ diff --git a/code/build.linux/synchdisk.o b/code/build.linux/synchdisk.o deleted file mode 100644 index 5cbf66e..0000000 Binary files a/code/build.linux/synchdisk.o and /dev/null differ diff --git a/code/build.linux/sysdep.o b/code/build.linux/sysdep.o deleted file mode 100644 index 2063c8b..0000000 Binary files a/code/build.linux/sysdep.o and /dev/null differ diff --git a/code/build.linux/thread.o b/code/build.linux/thread.o deleted file mode 100644 index a815af2..0000000 Binary files a/code/build.linux/thread.o and /dev/null differ diff --git a/code/build.linux/timer.o b/code/build.linux/timer.o deleted file mode 100644 index f8358e6..0000000 Binary files a/code/build.linux/timer.o and /dev/null differ diff --git a/code/build.linux/translate.o b/code/build.linux/translate.o deleted file mode 100644 index 32359c4..0000000 Binary files a/code/build.linux/translate.o and /dev/null differ diff --git a/code/filesys/filesys.h b/code/filesys/filesys.h index 743430c..b38b08c 100644 --- a/code/filesys/filesys.h +++ b/code/filesys/filesys.h @@ -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 }; diff --git a/code/filesys/openfile.h b/code/filesys/openfile.h index 2872476..af72c5c 100644 --- a/code/filesys/openfile.h +++ b/code/filesys/openfile.h @@ -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); } diff --git a/code/lib/sysdep.cc b/code/lib/sysdep.cc index a83c8da..c6f6dbd 100644 --- a/code/lib/sysdep.cc +++ b/code/lib/sysdep.cc @@ -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; diff --git a/code/machine/console.cc b/code/machine/console.cc index 9f9514c..f122beb 100644 --- a/code/machine/console.cc +++ b/code/machine/console.cc @@ -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); +} \ No newline at end of file diff --git a/code/machine/console.h b/code/machine/console.h index 24516a7..03226e9 100644 --- a/code/machine/console.h +++ b/code/machine/console.h @@ -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. diff --git a/code/machine/interrupt.h b/code/machine/interrupt.h index fefff93..7108b05 100644 --- a/code/machine/interrupt.h +++ b/code/machine/interrupt.h @@ -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 diff --git a/code/test/Makefile b/code/test/Makefile index db472c6..1ac0428 100644 --- a/code/test/Makefile +++ b/code/test/Makefile @@ -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. diff --git a/code/test/add b/code/test/add deleted file mode 100644 index 14aeee0..0000000 Binary files a/code/test/add and /dev/null differ diff --git a/code/test/consoleIO_test1 b/code/test/consoleIO_test1 deleted file mode 100644 index 8f4131f..0000000 Binary files a/code/test/consoleIO_test1 and /dev/null differ diff --git a/code/test/consoleIO_test1.c b/code/test/consoleIO_test1.c index 5de3402..aa8180b 100644 --- a/code/test/consoleIO_test1.c +++ b/code/test/consoleIO_test1.c @@ -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(); } diff --git a/code/test/consoleIO_test2 b/code/test/consoleIO_test2 deleted file mode 100644 index 540cf82..0000000 Binary files a/code/test/consoleIO_test2 and /dev/null differ diff --git a/code/test/file1.test b/code/test/file1.test new file mode 100644 index 0000000..e85d5b4 --- /dev/null +++ b/code/test/file1.test @@ -0,0 +1 @@ +abcdefghijklmnopqrstuvwxyz \ No newline at end of file diff --git a/code/test/fileIO_test1 b/code/test/fileIO_test1 deleted file mode 100644 index 192f089..0000000 Binary files a/code/test/fileIO_test1 and /dev/null differ diff --git a/code/test/fileIO_test2 b/code/test/fileIO_test2 deleted file mode 100644 index 3ea2bd4..0000000 Binary files a/code/test/fileIO_test2 and /dev/null differ diff --git a/code/test/halt b/code/test/halt deleted file mode 100644 index 66bd0c3..0000000 Binary files a/code/test/halt and /dev/null differ diff --git a/code/test/os_students.sh b/code/test/os_students.sh index 35cbfd7..3d714a3 100644 --- a/code/test/os_students.sh +++ b/code/test/os_students.sh @@ -1,3 +1,2 @@ make clean -make -d -../build.linux/nachos -e halt \ No newline at end of file +make run diff --git a/code/test/start.S b/code/test/start.S index 95fc506..5d0b18c 100644 --- a/code/test/start.S +++ b/code/test/start.S @@ -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 diff --git a/code/threads/kernel.h b/code/threads/kernel.h index d04e6f3..0f13c5a 100644 --- a/code/threads/kernel.h +++ b/code/threads/kernel.h @@ -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 diff --git a/code/userprog/exception.cc b/code/userprog/exception.cc index cdcd82f..c7be4ba 100644 --- a/code/userprog/exception.cc +++ b/code/userprog/exception.cc @@ -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(); } diff --git a/code/userprog/ksyscall.h b/code/userprog/ksyscall.h index c27fd41..bf1b9f3 100644 --- a/code/userprog/ksyscall.h +++ b/code/userprog/ksyscall.h @@ -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__ */ diff --git a/code/userprog/synchconsole.cc b/code/userprog/synchconsole.cc index 346ffe6..b786d7f 100644 --- a/code/userprog/synchconsole.cc +++ b/code/userprog/synchconsole.cc @@ -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 diff --git a/code/userprog/synchconsole.h b/code/userprog/synchconsole.h index b0f7a97..e412ff2 100644 --- a/code/userprog/synchconsole.h +++ b/code/userprog/synchconsole.h @@ -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 diff --git a/code/userprog/syscall.h b/code/userprog/syscall.h index 9fad2e3..ce6dd48 100644 --- a/code/userprog/syscall.h +++ b/code/userprog/syscall.h @@ -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 */ diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..06cced5 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,7 @@ +--- +services: + test: + build: . + user: '60139:60139' + volumes: + - './:/work'