6 Commits
clean ... hw1

Author SHA1 Message Date
ChenYen-Yen
549bc9bcdc merge update 2024-10-22 16:29:46 +08:00
ChenYen-Yen
b18dbf056f update PrintInt and change PutString to PutInt 2024-10-22 16:27:49 +08:00
5b1cd5e1cf Add: README
Fix: newline when PrintInt outputs 0
2024-10-05 04:13:43 +08:00
施羿廷
486f032cf0 Merge branch 'ytshih-hw1' into 'main'
HW1

See merge request cs_os_group_20/cs_os_project_20_hw!1
2024-10-04 19:53:08 +00:00
施羿廷
ba9ef819ba HW1 2024-10-04 19:53:08 +00:00
ChenYen-Yen
0284b75ab6 try make -d 2024-10-02 15:00:45 +08:00
62 changed files with 423 additions and 194 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.o

13
Dockerfile Normal file
View 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"]

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
# Intro. to OS HW1
## Docker Compose usage
Install docker and docker-compose if not installed.
1. Change uid / gid to yours in `Dockerfile` and `docker-compose.yaml`.
2. Run `docker compose build` to build Docker image.
3. Run `docker compose run test` to launch testing environment.
## Makefile
First, `cd` into `code` directory.
- `make clean` to clean previous build.
- `make` to build.
- `make run` to run tests.

14
code/Makefile Normal file
View 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

View File

@@ -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:

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.

View File

@@ -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
}; };

View 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); }

View 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;

View File

@@ -172,3 +172,13 @@ ConsoleOutput::PutChar(char ch)
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt); kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
} }
void
ConsoleOutput::PutInt(int value)
{
ASSERT(putBusy == FALSE);
char *printStr = (char*)malloc(sizeof(char)*15);
sprintf(printStr, "%d\n", value);
WriteFile(writeFileNo, printStr, strlen(printStr)*sizeof(char));
putBusy = TRUE;
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
}

View File

@@ -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 PutInt(int n);
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.

View File

@@ -359,3 +359,8 @@ Interrupt::DumpState()
cout << "\nEnd of pending interrupts\n"; cout << "\nEnd of pending interrupts\n";
} }
void
Interrupt::PrintInt(int value)
{
return kernel->PrintInt(value);
}

View File

@@ -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

View File

@@ -107,13 +107,14 @@ LD = $(GCCDIR)ld
INCDIR =-I../userprog -I../lib 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/ 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) ifeq ($(hosttype),unknown)
PROGRAMS = unknownhost PROGRAMS = unknownhost
else else
# change this if you create a new test program! # change this if you create a new test program!
# PROGRAMS = add halt consoleIO_test1 consoleIO_test2 fileIO_test1 fileIO_test2 PROGRAMS = add halt consoleIO_test1 consoleIO_test2 fileIO_test1 fileIO_test2
PROGRAMS = halt # PROGRAMS = halt
endif endif
all: $(PROGRAMS) all: $(PROGRAMS)
@@ -196,6 +197,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.

Binary file not shown.

Binary file not shown.

View File

@@ -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();
} }

Binary file not shown.

1
code/test/file1.test Normal file
View File

@@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyz

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,2 @@
make clean make clean
make make run
../build.linux/nachos -e halt

View File

@@ -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

View File

@@ -308,4 +308,7 @@ int Kernel::CreateFile(char *filename)
return fileSystem->Create(filename); return fileSystem->Create(filename);
} }
void Kernel::PrintInt(int value)
{
return synchConsoleOut->PutInt(value);
}

View File

@@ -36,15 +36,17 @@ 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 void PrintInt(int n);
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 +68,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

View File

@@ -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();
} }

View File

@@ -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,48 @@ 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) {
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;
}
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;
} }

View File

@@ -106,6 +106,15 @@ SynchConsoleOutput::PutChar(char ch)
lock->Release(); lock->Release();
} }
void
SynchConsoleOutput::PutInt(int value)
{
lock->Acquire();
consoleOutput->PutInt(value);
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

View File

@@ -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 PutInt(int value);
private: private:
ConsoleOutput *consoleOutput;// the hardware display ConsoleOutput *consoleOutput;// the hardware display

View File

@@ -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
View File

@@ -0,0 +1,7 @@
---
services:
test:
build: .
user: '60139:60139'
volumes:
- './:/work'