10 Commits
clean ... hw2

Author SHA1 Message Date
bf78b95c9d Remove: sanitizer flag in compile and link 2024-11-02 08:11:33 +08:00
5f06249b01 Fix: Custom test CI script 2024-11-02 08:04:02 +08:00
Yi-Ting Shih
b4987f1f70 Merge branch 'ytshih/hw2' into 'main'
Ytshih/hw2

See merge request cs_os_group_20/cs_os_project_20_hw!2
2024-11-02 07:58:12 +08:00
Yi-Ting Shih
4912fe4736 Ytshih/hw2 2024-11-02 07:58:12 +08:00
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
73 changed files with 1156 additions and 4456 deletions

2
.gitignore vendored Normal file
View File

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

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
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 apt-get -y install fish vim less gdb
RUN groupadd -g 60139 ytshih && useradd -g 60139 -u 60139 ytshih
WORKDIR /work
ENTRYPOINT ["/usr/bin/env"]
CMD ["fish"]

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.

17
code/Makefile Normal file
View File

@@ -0,0 +1,17 @@
.PHONY: all clean run
all:
make -C build.linux depend
make -C build.linux -j 16
make -C test -j 16
clean:
make -C build.linux distclean
make -C test distclean
run:
make -C test run
debug:
make -C test debug

Binary file not shown.

View File

@@ -200,8 +200,8 @@ DEFINES = -DFILESYS_STUB -DRDATA -DSIM_FIX
# break the thread system. You might want to use -fno-inline if
# you need to call some inline functions from the debugger.
CFLAGS = -g -Wall $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32
LDFLAGS = -m32
CFLAGS = -g -Wall -Wextra $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32 # -fsanitize=address,undefined
LDFLAGS = -m32 # -fsanitize=address,undefined
CPP_AS_FLAGS= -m32
#####################################################################
@@ -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:

File diff suppressed because it is too large Load Diff

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

@@ -62,7 +62,6 @@ class FileSystem {
bool Remove(char *name) { return Unlink(name) == 0; }
OpenFile *fileDescriptorTable[20];
};
#else // FILESYS

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

View File

@@ -172,3 +172,13 @@ ConsoleOutput::PutChar(char ch)
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,
// and return immediately. "callWhenDone"
// will called when the I/O completes.
void PutInt(int n);
void CallBack(); // Invoked when next character can be put
// out to the display.

View File

@@ -23,6 +23,7 @@
#include "copyright.h"
#include "interrupt.h"
#include "main.h"
#include "synchconsole.h"
// String definitions for debugging messages
@@ -340,7 +341,7 @@ static void
PrintPending (PendingInterrupt *pending)
{
cout << "Interrupt handler "<< intTypeNames[pending->type];
cout << ", scheduled at " << pending->when;
cout << ", scheduled at " << pending->when << endl;
}
//----------------------------------------------------------------------
@@ -359,3 +360,8 @@ Interrupt::DumpState()
cout << "\nEnd of pending interrupts\n";
}
void
Interrupt::PrintInt(int value)
{
kernel->synchConsoleOut->PutInt(value);
}

View File

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

View File

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

View File

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

View File

@@ -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 test
# PROGRAMS = halt
endif
all: $(PROGRAMS)
@@ -188,6 +189,11 @@ fileIO_test3: fileIO_test3.o start.o
$(LD) $(LDFLAGS) start.o fileIO_test3.o -o fileIO_test3.coff
$(COFF2NOFF) fileIO_test3.coff fileIO_test3
test.o: test.c
$(CC) $(CFLAGS) -c test.c
test: test.o start.o
$(LD) $(LDFLAGS) start.o test.o -o test.coff
$(COFF2NOFF) test.coff test
clean:
$(RM) -f *.o *.ii
@@ -196,6 +202,14 @@ clean:
distclean: clean
$(RM) -f $(PROGRAMS)
run: $(PROGRAMS)
timeout 1 $(NACHOS) -e consoleIO_test1 -e consoleIO_test2
echo 'done'
debug: $(PROGRAMS)
timeout 1 $(NACHOS) -e consoleIO_test1 -e consoleIO_test2 -d +
unknownhost:
@echo Host type could not be determined.
@echo make is terminating.

Binary file not shown.

Binary file not shown.

View File

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

Binary file not shown.

View File

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

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,4 @@
make clean
make distclean
make
../build.linux/nachos -e halt
timeout 1 ../build.linux/nachos -e consoleIO_test1 -e consoleIO_test2
echo 'done'

View File

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

6
code/test/test.c Normal file
View File

@@ -0,0 +1,6 @@
#include "syscall.h"
int main()
{
Exit(0);
}

View File

@@ -26,6 +26,8 @@
Kernel::Kernel(int argc, char **argv)
{
execfileNum = 0;
threadNum = 0;
randomSlice = FALSE;
debugUserProg = FALSE;
consoleIn = NULL; // default is stdin
@@ -113,6 +115,7 @@ Kernel::Initialize()
#endif // FILESYS_STUB
postOfficeIn = new PostOfficeInput(10);
postOfficeOut = new PostOfficeOutput(reliability);
frameTable = new FrameTable;
interrupt->Enable();
}
@@ -135,6 +138,7 @@ Kernel::~Kernel()
delete fileSystem;
delete postOfficeIn;
delete postOfficeOut;
delete frameTable;
Exit(0);
}
@@ -250,12 +254,10 @@ Kernel::NetworkTest() {
void ForkExecute(Thread *t)
{
if ( !t->space->Load(t->getName()) ) {
if (!t->space->Load(t->getName()))
return; // executable not found
}
t->space->Execute(t->getName());
}
void Kernel::ExecAll()
@@ -273,9 +275,8 @@ int Kernel::Exec(char* name)
t[threadNum] = new Thread(name, threadNum);
t[threadNum]->space = new AddrSpace();
t[threadNum]->Fork((VoidFunctionPtr) &ForkExecute, (void *)t[threadNum]);
threadNum++;
return threadNum-1;
return threadNum++;
/*
cout << "Total threads number is " << execfileNum << endl;
for (int n=1;n<=execfileNum;n++) {
@@ -308,4 +309,7 @@ int Kernel::CreateFile(char *filename)
return fileSystem->Create(filename);
}
void Kernel::PrintInt(int value)
{
return synchConsoleOut->PutInt(value);
}

View File

@@ -44,6 +44,8 @@ class Kernel {
void NetworkTest(); // interactive 2-machine network test
Thread* getThread(int threadID){return t[threadID];}
void PrintInt(int n);
int CreateFile(char* filename); // fileSystem call
// These are public for notational convenience; really,
@@ -61,6 +63,7 @@ class Kernel {
FileSystem *fileSystem;
PostOfficeInput *postOfficeIn;
PostOfficeOutput *postOfficeOut;
FrameTable *frameTable;
int hostName; // machine identifier

View File

@@ -57,6 +57,71 @@ SwapHeader (NoffHeader *noffH)
#endif
}
FrameTable::Node::Node(int idx):
next(nullptr), idx(idx) {}
FrameTable::FrameTable()
{
available = NumPhysPages;
useCount = new int[NumPhysPages];
begin = end = new FrameTable::Node;
for (int i = 0; i < NumPhysPages; i++) {
useCount[i] = 0;
end->idx = i;
end->next = new FrameTable::Node;
end = end->next;
}
}
FrameTable::~FrameTable()
{
delete[] useCount;
while (begin != end) {
FrameTable::Node *tmpNode = begin;
begin = begin->next;
delete tmpNode;
}
delete begin;
}
int FrameTable::Allocate()
{
if (available == 0)
return -1;
int ret = begin->idx;
Node *tmp = begin;
begin = begin->next;
delete tmp;
--available;
useCount[ret]++;
bzero(kernel->machine->mainMemory + ret * PageSize, PageSize);
//cerr << "Allocated at page: " << ret << endl;
return ret;
}
void FrameTable::Release(int phyPageNum)
{
useCount[phyPageNum]--;
if (useCount[phyPageNum] > 0)
return;
++available;
//cerr << "Release page: " << end->idx << endl;
end->idx = phyPageNum;
end->next = new FrameTable::Node;
}
size_t FrameTable::RemainSize()
{
return available;
}
//----------------------------------------------------------------------
// AddrSpace::AddrSpace
// Create an address space to run a user program.
@@ -66,20 +131,7 @@ SwapHeader (NoffHeader *noffH)
//----------------------------------------------------------------------
AddrSpace::AddrSpace()
{
pageTable = new TranslationEntry[NumPhysPages];
for (int i = 0; i < NumPhysPages; i++) {
pageTable[i].virtualPage = i; // for now, virt page # = phys page #
pageTable[i].physicalPage = i;
pageTable[i].valid = TRUE;
pageTable[i].use = FALSE;
pageTable[i].dirty = FALSE;
pageTable[i].readOnly = FALSE;
}
// zero out the entire address space
bzero(kernel->machine->mainMemory, MemorySize);
}
{}
//----------------------------------------------------------------------
// AddrSpace::~AddrSpace
@@ -88,7 +140,10 @@ AddrSpace::AddrSpace()
AddrSpace::~AddrSpace()
{
delete pageTable;
for (int i = 0; i < NumPhysPages; i++)
if (pageTable[i].use == TRUE)
kernel->frameTable->Release(pageTable[i].physicalPage);
delete[] pageTable;
}
@@ -105,6 +160,7 @@ AddrSpace::~AddrSpace()
bool
AddrSpace::Load(char *fileName)
{
//cerr << "AddrSpace::Load" << endl;
OpenFile *executable = kernel->fileSystem->Open(fileName);
NoffHeader noffH;
unsigned int size;
@@ -124,6 +180,11 @@ AddrSpace::Load(char *fileName)
// how big is address space?
size = noffH.code.size + noffH.readonlyData.size + noffH.initData.size +
noffH.uninitData.size + UserStackSize;
//cerr << noffH.code.size << ' '
// << noffH.readonlyData.size << ' '
// << noffH.initData.size << ' '
// << noffH.uninitData.size << ' '
// << UserStackSize << endl;
// we need to increase the size
// to leave room for the stack
#else
@@ -131,6 +192,10 @@ AddrSpace::Load(char *fileName)
size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
+ UserStackSize; // we need to increase the size
// to leave room for the stack
//cerr << noffH.code.size << ' '
// << noffH.initData.size << ' '
// << noffH.uninitData.size << ' '
// << UserStackSize << endl;
#endif
numPages = divRoundUp(size, PageSize);
size = numPages * PageSize;
@@ -140,32 +205,60 @@ AddrSpace::Load(char *fileName)
// at least until we have
// virtual memory
pageTable = new TranslationEntry[numPages];
for (int i = 0; i < numPages; i++) {
pageTable[i].virtualPage = i;
pageTable[i].physicalPage = -1;
pageTable[i].valid = TRUE;
pageTable[i].use = FALSE;
pageTable[i].dirty = FALSE;
pageTable[i].readOnly = FALSE;
}
DEBUG(dbgAddr, "Initializing address space: " << numPages << ", " << size);
// then, copy in the code and data segments into memory
// Note: this code assumes that virtual address = physical address
if (noffH.code.size > 0) {
DEBUG(dbgAddr, "Initializing code segment.");
DEBUG(dbgAddr, noffH.code.virtualAddr << ", " << noffH.code.size);
for (size_t cur = 0; cur < (size_t)noffH.code.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.code.size - cur);
Translate(noffH.code.virtualAddr + cur, &physAddr, 1);
//cerr << "physAddr, size: " << physAddr << ' ' << size << endl;
executable->ReadAt(
&(kernel->machine->mainMemory[noffH.code.virtualAddr]),
noffH.code.size, noffH.code.inFileAddr);
&(kernel->machine->mainMemory[physAddr]), size,
noffH.code.inFileAddr + cur);
}
}
if (noffH.initData.size > 0) {
DEBUG(dbgAddr, "Initializing data segment.");
DEBUG(dbgAddr, noffH.initData.virtualAddr << ", " << noffH.initData.size);
for (size_t cur = 0; cur < (size_t)noffH.initData.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.initData.size - cur);
Translate(noffH.initData.virtualAddr + cur, &physAddr, 1);
executable->ReadAt(
&(kernel->machine->mainMemory[noffH.initData.virtualAddr]),
noffH.initData.size, noffH.initData.inFileAddr);
&(kernel->machine->mainMemory[physAddr]), size,
noffH.initData.inFileAddr + cur);
}
}
#ifdef RDATA
if (noffH.readonlyData.size > 0) {
DEBUG(dbgAddr, "Initializing read only data segment.");
DEBUG(dbgAddr, noffH.readonlyData.virtualAddr << ", " << noffH.readonlyData.size);
for (size_t cur = 0; cur < (size_t)noffH.readonlyData.size; cur += PageSize) {
size_t physAddr, size = min((size_t)PageSize, noffH.readonlyData.size - cur);
Translate(noffH.readonlyData.virtualAddr + cur, &physAddr, 1);
executable->ReadAt(
&(kernel->machine->mainMemory[noffH.readonlyData.virtualAddr]),
noffH.readonlyData.size, noffH.readonlyData.inFileAddr);
&(kernel->machine->mainMemory[physAddr]),
size, noffH.readonlyData.inFileAddr + cur);
}
}
#endif
@@ -185,7 +278,7 @@ AddrSpace::Load(char *fileName)
void
AddrSpace::Execute(char* fileName)
{
//cerr << "AddrSpace::Execute" << endl;
kernel->currentThread->space = this;
this->InitRegisters(); // set the initial register values
@@ -288,6 +381,13 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
}
pfn = pte->physicalPage;
if (pfn == -1) {
pfn = pte->physicalPage = kernel->frameTable->Allocate();
if (pfn == -1) {
DEBUG(dbgAddr, "Memory Limit exceeded");
return MemoryLimitException;
}
}
// if the pageFrame is too big, there is something really wrong!
// An invalid translation was loaded into the page table or TLB.
@@ -310,7 +410,3 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
return NoException;
}

View File

@@ -18,6 +18,28 @@
#define UserStackSize 1024 // increase this as necessary!
class FrameTable {
public:
FrameTable();
~FrameTable();
int Allocate();
void Release(int phyPageNum);
size_t RemainSize();
private:
struct Node {
Node *next;
int idx;
Node(int idx = -1);
};
Node *begin, *end;
size_t available;
int *useCount;
};
class AddrSpace {
public:
AddrSpace(); // Create an address space.
@@ -40,8 +62,7 @@ class AddrSpace {
ExceptionType Translate(unsigned int vaddr, unsigned int *paddr, int mode);
private:
TranslationEntry *pageTable; // Assume linear page table translation
// for now!
TranslationEntry *pageTable;
unsigned int numPages; // Number of pages in the virtual
// address space

View File

@@ -118,6 +118,92 @@ ExceptionHandler(ExceptionType which)
cout << "return value:" << val << endl;
kernel->currentThread->Finish();
break;
case SC_PrintInt:
DEBUG(dbgAddr, "Printing int\n");
val = (int)kernel->machine->ReadRegister(4);
SysPrintInt(val);
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Open:
DEBUG(dbgAddr, "Open file\n");
{
val = kernel->machine->ReadRegister(4);
char *name = &(kernel->machine->mainMemory[val]);
OpenFileId ret = SysOpen(name);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Read:
DEBUG(dbgAddr, "Read file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
int ret = SysRead(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Write:
DEBUG(dbgAddr, "Write file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
// fprintf(stderr, "buffer: %p\n", buffer);
// cerr << "size: " << size << endl;
// cerr << "id: " << id << endl;
int ret = SysWrite(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Close:
DEBUG(dbgAddr, "Close file\n");
{
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(4);
int ret = SysClose(id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
default:
cerr << "Unexpected system call " << type << "\n";
break;

View File

@@ -11,6 +11,8 @@
#ifndef __USERPROG_KSYSCALL_H__
#define __USERPROG_KSYSCALL_H__
#define INT_BUF_LENGTH 13
#include "kernel.h"
#include "synchconsole.h"
@@ -34,5 +36,43 @@ int SysCreate(char *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;
}
#endif /* ! __USERPROG_KSYSCALL_H__ */

View File

@@ -106,6 +106,15 @@ SynchConsoleOutput::PutChar(char ch)
lock->Release();
}
void
SynchConsoleOutput::PutInt(int value)
{
lock->Acquire();
consoleOutput->PutInt(value);
waitFor->P();
lock->Release();
}
//----------------------------------------------------------------------
// SynchConsoleOutput::CallBack
// Interrupt handler called when it's safe to send the next

View File

@@ -41,6 +41,7 @@ class SynchConsoleOutput : public CallBackObj {
~SynchConsoleOutput();
void PutChar(char ch); // Write a character, waiting if necessary
void PutInt(int value);
private:
ConsoleOutput *consoleOutput;// the hardware display

View File

@@ -34,6 +34,9 @@
#define SC_ExecV 13
#define SC_ThreadExit 14
#define SC_ThreadJoin 15
#define SC_PrintInt 16
#define SC_Add 42
#define SC_MSG 100
@@ -177,6 +180,8 @@ int ThreadJoin(ThreadId id);
*/
void ThreadExit(int ExitCode);
void PrintInt(int number);
#endif /* IN_ASM */
#endif /* SYSCALL_H */

7
docker-compose.yaml Normal file
View File

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