Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf78b95c9d | |||
| 5f06249b01 | |||
|
|
b4987f1f70 | ||
|
|
4912fe4736 | ||
|
|
549bc9bcdc | ||
|
|
b18dbf056f | ||
| 5b1cd5e1cf | |||
|
|
486f032cf0 | ||
|
|
ba9ef819ba | ||
|
|
0284b75ab6 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
*.coff
|
||||||
16
Dockerfile
Normal file
16
Dockerfile
Normal 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
17
README.md
Normal 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
17
code/Makefile
Normal 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.
@@ -200,8 +200,8 @@ DEFINES = -DFILESYS_STUB -DRDATA -DSIM_FIX
|
|||||||
# break the thread system. You might want to use -fno-inline if
|
# break the thread system. You might want to use -fno-inline if
|
||||||
# you need to call some inline functions from the debugger.
|
# you need to call some inline functions from the debugger.
|
||||||
|
|
||||||
CFLAGS = -g -Wall $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32
|
CFLAGS = -g -Wall -Wextra $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32 # -fsanitize=address,undefined
|
||||||
LDFLAGS = -m32
|
LDFLAGS = -m32 # -fsanitize=address,undefined
|
||||||
CPP_AS_FLAGS= -m32
|
CPP_AS_FLAGS= -m32
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
@@ -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:
|
||||||
|
|||||||
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.
@@ -62,7 +62,6 @@ class FileSystem {
|
|||||||
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
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ int
|
|||||||
OpenForWrite(char *name)
|
OpenForWrite(char *name)
|
||||||
{
|
{
|
||||||
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||||
|
// cerr << "OpenForWrite name, fd: " << (int)name << ", " << fd << endl;
|
||||||
|
|
||||||
ASSERT(fd >= 0);
|
ASSERT(fd >= 0);
|
||||||
return fd;
|
return fd;
|
||||||
@@ -325,6 +326,7 @@ int
|
|||||||
OpenForReadWrite(char *name, bool crashOnError)
|
OpenForReadWrite(char *name, bool crashOnError)
|
||||||
{
|
{
|
||||||
int fd = open(name, O_RDWR, 0);
|
int fd = open(name, O_RDWR, 0);
|
||||||
|
// cerr << "OpenForReadWrite name, fd: " << (int)name << ", " << fd << endl;
|
||||||
|
|
||||||
ASSERT(!crashOnError || fd >= 0);
|
ASSERT(!crashOnError || fd >= 0);
|
||||||
return fd;
|
return fd;
|
||||||
|
|||||||
@@ -172,3 +172,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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "copyright.h"
|
#include "copyright.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "synchconsole.h"
|
||||||
|
|
||||||
// String definitions for debugging messages
|
// String definitions for debugging messages
|
||||||
|
|
||||||
@@ -340,7 +341,7 @@ static void
|
|||||||
PrintPending (PendingInterrupt *pending)
|
PrintPending (PendingInterrupt *pending)
|
||||||
{
|
{
|
||||||
cout << "Interrupt handler "<< intTypeNames[pending->type];
|
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";
|
cout << "\nEnd of pending interrupts\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Interrupt::PrintInt(int value)
|
||||||
|
{
|
||||||
|
kernel->synchConsoleOut->PutInt(value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,10 +13,17 @@
|
|||||||
|
|
||||||
// Textual names of the exceptions that can be generated by user program
|
// Textual names of the exceptions that can be generated by user program
|
||||||
// execution, for debugging.
|
// execution, for debugging.
|
||||||
static char* exceptionNames[] = { "no exception", "syscall",
|
static char* exceptionNames[] = {
|
||||||
"page fault/no TLB entry", "page read only",
|
"no exception",
|
||||||
"bus error", "address error", "overflow",
|
"syscall",
|
||||||
"illegal instruction" };
|
"page fault/no TLB entry",
|
||||||
|
"page read only",
|
||||||
|
"bus error",
|
||||||
|
"address error",
|
||||||
|
"overflow",
|
||||||
|
"illegal instruction",
|
||||||
|
"bad memory allocation"
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// CheckEndian
|
// CheckEndian
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ const int NumPhysPages = 128;
|
|||||||
const int MemorySize = (NumPhysPages * PageSize);
|
const int MemorySize = (NumPhysPages * PageSize);
|
||||||
const int TLBSize = 4; // if there is a TLB, make it small
|
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.
|
SyscallException, // A program executed a system call.
|
||||||
PageFaultException, // No valid translation found
|
PageFaultException, // No valid translation found
|
||||||
ReadOnlyException, // Write attempted to page marked
|
ReadOnlyException, // Write attempted to page marked
|
||||||
@@ -52,6 +53,7 @@ enum ExceptionType { NoException, // Everything ok!
|
|||||||
// address space
|
// address space
|
||||||
OverflowException, // Integer overflow in add or sub.
|
OverflowException, // Integer overflow in add or sub.
|
||||||
IllegalInstrException, // Unimplemented or reserved instr.
|
IllegalInstrException, // Unimplemented or reserved instr.
|
||||||
|
MemoryLimitException, // Bad allocation
|
||||||
|
|
||||||
NumExceptionTypes
|
NumExceptionTypes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 (tlb == NULL) { // => page table => vpn is index into table
|
||||||
if (vpn >= pageTableSize) {
|
if (vpn >= pageTableSize) {
|
||||||
DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
|
DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
|
||||||
|
DEBUG(dbgAddr, "vpn, pageTableSize, NumPhysPages: " << vpn << ' ' << pageTableSize << ' ' << NumPhysPages);
|
||||||
return AddressErrorException;
|
return AddressErrorException;
|
||||||
} else if (!pageTable[vpn].valid) {
|
} else if (!pageTable[vpn].valid) {
|
||||||
DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
|
DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
|
||||||
@@ -233,6 +234,13 @@ Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
|
|||||||
return ReadOnlyException;
|
return ReadOnlyException;
|
||||||
}
|
}
|
||||||
pageFrame = entry->physicalPage;
|
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!
|
// if the pageFrame is too big, there is something really wrong!
|
||||||
// An invalid translation was loaded into the page table or TLB.
|
// An invalid translation was loaded into the page table or TLB.
|
||||||
|
|||||||
@@ -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 test
|
||||||
PROGRAMS = halt
|
# PROGRAMS = halt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
@@ -188,6 +189,11 @@ fileIO_test3: fileIO_test3.o start.o
|
|||||||
$(LD) $(LDFLAGS) start.o fileIO_test3.o -o fileIO_test3.coff
|
$(LD) $(LDFLAGS) start.o fileIO_test3.o -o fileIO_test3.coff
|
||||||
$(COFF2NOFF) fileIO_test3.coff fileIO_test3
|
$(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:
|
clean:
|
||||||
$(RM) -f *.o *.ii
|
$(RM) -f *.o *.ii
|
||||||
@@ -196,6 +202,14 @@ clean:
|
|||||||
distclean: clean
|
distclean: clean
|
||||||
$(RM) -f $(PROGRAMS)
|
$(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:
|
unknownhost:
|
||||||
@echo Host type could not be determined.
|
@echo Host type could not be determined.
|
||||||
@echo make is terminating.
|
@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"
|
#include "syscall.h"
|
||||||
|
|
||||||
int
|
int main() {
|
||||||
main()
|
|
||||||
{
|
|
||||||
int n;
|
int n;
|
||||||
for (n=9;n>5;n--) {
|
for (n = 9; n > 5; n--)
|
||||||
PrintInt(n);
|
PrintInt(n);
|
||||||
}
|
return 0;
|
||||||
Halt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,13 +1,11 @@
|
|||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
int
|
int main()
|
||||||
main()
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
for (n=15;n<=19;n++){
|
for (n=15;n<=19;n++){
|
||||||
|
|
||||||
PrintInt(n);
|
PrintInt(n);
|
||||||
}
|
}
|
||||||
Halt();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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,4 @@
|
|||||||
make clean
|
make distclean
|
||||||
make
|
make
|
||||||
../build.linux/nachos -e halt
|
timeout 1 ../build.linux/nachos -e consoleIO_test1 -e consoleIO_test2
|
||||||
|
echo 'done'
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
6
code/test/test.c
Normal file
6
code/test/test.c
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Exit(0);
|
||||||
|
}
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
Kernel::Kernel(int argc, char **argv)
|
Kernel::Kernel(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
execfileNum = 0;
|
||||||
|
threadNum = 0;
|
||||||
randomSlice = FALSE;
|
randomSlice = FALSE;
|
||||||
debugUserProg = FALSE;
|
debugUserProg = FALSE;
|
||||||
consoleIn = NULL; // default is stdin
|
consoleIn = NULL; // default is stdin
|
||||||
@@ -113,6 +115,7 @@ Kernel::Initialize()
|
|||||||
#endif // FILESYS_STUB
|
#endif // FILESYS_STUB
|
||||||
postOfficeIn = new PostOfficeInput(10);
|
postOfficeIn = new PostOfficeInput(10);
|
||||||
postOfficeOut = new PostOfficeOutput(reliability);
|
postOfficeOut = new PostOfficeOutput(reliability);
|
||||||
|
frameTable = new FrameTable;
|
||||||
|
|
||||||
interrupt->Enable();
|
interrupt->Enable();
|
||||||
}
|
}
|
||||||
@@ -135,6 +138,7 @@ Kernel::~Kernel()
|
|||||||
delete fileSystem;
|
delete fileSystem;
|
||||||
delete postOfficeIn;
|
delete postOfficeIn;
|
||||||
delete postOfficeOut;
|
delete postOfficeOut;
|
||||||
|
delete frameTable;
|
||||||
|
|
||||||
Exit(0);
|
Exit(0);
|
||||||
}
|
}
|
||||||
@@ -250,12 +254,10 @@ Kernel::NetworkTest() {
|
|||||||
|
|
||||||
void ForkExecute(Thread *t)
|
void ForkExecute(Thread *t)
|
||||||
{
|
{
|
||||||
if ( !t->space->Load(t->getName()) ) {
|
if (!t->space->Load(t->getName()))
|
||||||
return; // executable not found
|
return; // executable not found
|
||||||
}
|
|
||||||
|
|
||||||
t->space->Execute(t->getName());
|
t->space->Execute(t->getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::ExecAll()
|
void Kernel::ExecAll()
|
||||||
@@ -273,9 +275,8 @@ int Kernel::Exec(char* name)
|
|||||||
t[threadNum] = new Thread(name, threadNum);
|
t[threadNum] = new Thread(name, threadNum);
|
||||||
t[threadNum]->space = new AddrSpace();
|
t[threadNum]->space = new AddrSpace();
|
||||||
t[threadNum]->Fork((VoidFunctionPtr) &ForkExecute, (void *)t[threadNum]);
|
t[threadNum]->Fork((VoidFunctionPtr) &ForkExecute, (void *)t[threadNum]);
|
||||||
threadNum++;
|
|
||||||
|
|
||||||
return threadNum-1;
|
return threadNum++;
|
||||||
/*
|
/*
|
||||||
cout << "Total threads number is " << execfileNum << endl;
|
cout << "Total threads number is " << execfileNum << endl;
|
||||||
for (int n=1;n<=execfileNum;n++) {
|
for (int n=1;n<=execfileNum;n++) {
|
||||||
@@ -308,4 +309,7 @@ int Kernel::CreateFile(char *filename)
|
|||||||
return fileSystem->Create(filename);
|
return fileSystem->Create(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kernel::PrintInt(int value)
|
||||||
|
{
|
||||||
|
return synchConsoleOut->PutInt(value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ class Kernel {
|
|||||||
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];}
|
||||||
|
|
||||||
|
void PrintInt(int n);
|
||||||
|
|
||||||
int CreateFile(char* filename); // fileSystem call
|
int CreateFile(char* filename); // fileSystem call
|
||||||
|
|
||||||
// These are public for notational convenience; really,
|
// These are public for notational convenience; really,
|
||||||
@@ -61,6 +63,7 @@ class Kernel {
|
|||||||
FileSystem *fileSystem;
|
FileSystem *fileSystem;
|
||||||
PostOfficeInput *postOfficeIn;
|
PostOfficeInput *postOfficeIn;
|
||||||
PostOfficeOutput *postOfficeOut;
|
PostOfficeOutput *postOfficeOut;
|
||||||
|
FrameTable *frameTable;
|
||||||
|
|
||||||
int hostName; // machine identifier
|
int hostName; // machine identifier
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,71 @@ SwapHeader (NoffHeader *noffH)
|
|||||||
#endif
|
#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
|
// AddrSpace::AddrSpace
|
||||||
// Create an address space to run a user program.
|
// Create an address space to run a user program.
|
||||||
@@ -66,20 +131,7 @@ SwapHeader (NoffHeader *noffH)
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
AddrSpace::AddrSpace()
|
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
|
// AddrSpace::~AddrSpace
|
||||||
@@ -88,7 +140,10 @@ AddrSpace::AddrSpace()
|
|||||||
|
|
||||||
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
|
bool
|
||||||
AddrSpace::Load(char *fileName)
|
AddrSpace::Load(char *fileName)
|
||||||
{
|
{
|
||||||
|
//cerr << "AddrSpace::Load" << endl;
|
||||||
OpenFile *executable = kernel->fileSystem->Open(fileName);
|
OpenFile *executable = kernel->fileSystem->Open(fileName);
|
||||||
NoffHeader noffH;
|
NoffHeader noffH;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
@@ -124,6 +180,11 @@ AddrSpace::Load(char *fileName)
|
|||||||
// how big is address space?
|
// how big is address space?
|
||||||
size = noffH.code.size + noffH.readonlyData.size + noffH.initData.size +
|
size = noffH.code.size + noffH.readonlyData.size + noffH.initData.size +
|
||||||
noffH.uninitData.size + UserStackSize;
|
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
|
// we need to increase the size
|
||||||
// to leave room for the stack
|
// to leave room for the stack
|
||||||
#else
|
#else
|
||||||
@@ -131,6 +192,10 @@ AddrSpace::Load(char *fileName)
|
|||||||
size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
|
size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
|
||||||
+ UserStackSize; // we need to increase the size
|
+ UserStackSize; // we need to increase the size
|
||||||
// to leave room for the stack
|
// to leave room for the stack
|
||||||
|
//cerr << noffH.code.size << ' '
|
||||||
|
// << noffH.initData.size << ' '
|
||||||
|
// << noffH.uninitData.size << ' '
|
||||||
|
// << UserStackSize << endl;
|
||||||
#endif
|
#endif
|
||||||
numPages = divRoundUp(size, PageSize);
|
numPages = divRoundUp(size, PageSize);
|
||||||
size = numPages * PageSize;
|
size = numPages * PageSize;
|
||||||
@@ -140,32 +205,60 @@ AddrSpace::Load(char *fileName)
|
|||||||
// at least until we have
|
// at least until we have
|
||||||
// virtual memory
|
// 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);
|
DEBUG(dbgAddr, "Initializing address space: " << numPages << ", " << size);
|
||||||
|
|
||||||
// then, copy in the code and data segments into memory
|
// then, copy in the code and data segments into memory
|
||||||
// Note: this code assumes that virtual address = physical address
|
|
||||||
if (noffH.code.size > 0) {
|
if (noffH.code.size > 0) {
|
||||||
DEBUG(dbgAddr, "Initializing code segment.");
|
DEBUG(dbgAddr, "Initializing code segment.");
|
||||||
DEBUG(dbgAddr, noffH.code.virtualAddr << ", " << noffH.code.size);
|
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(
|
executable->ReadAt(
|
||||||
&(kernel->machine->mainMemory[noffH.code.virtualAddr]),
|
&(kernel->machine->mainMemory[physAddr]), size,
|
||||||
noffH.code.size, noffH.code.inFileAddr);
|
noffH.code.inFileAddr + cur);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (noffH.initData.size > 0) {
|
if (noffH.initData.size > 0) {
|
||||||
DEBUG(dbgAddr, "Initializing data segment.");
|
DEBUG(dbgAddr, "Initializing data segment.");
|
||||||
DEBUG(dbgAddr, noffH.initData.virtualAddr << ", " << noffH.initData.size);
|
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(
|
executable->ReadAt(
|
||||||
&(kernel->machine->mainMemory[noffH.initData.virtualAddr]),
|
&(kernel->machine->mainMemory[physAddr]), size,
|
||||||
noffH.initData.size, noffH.initData.inFileAddr);
|
noffH.initData.inFileAddr + cur);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RDATA
|
#ifdef RDATA
|
||||||
if (noffH.readonlyData.size > 0) {
|
if (noffH.readonlyData.size > 0) {
|
||||||
DEBUG(dbgAddr, "Initializing read only data segment.");
|
DEBUG(dbgAddr, "Initializing read only data segment.");
|
||||||
DEBUG(dbgAddr, noffH.readonlyData.virtualAddr << ", " << noffH.readonlyData.size);
|
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(
|
executable->ReadAt(
|
||||||
&(kernel->machine->mainMemory[noffH.readonlyData.virtualAddr]),
|
&(kernel->machine->mainMemory[physAddr]),
|
||||||
noffH.readonlyData.size, noffH.readonlyData.inFileAddr);
|
size, noffH.readonlyData.inFileAddr + cur);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -185,7 +278,7 @@ AddrSpace::Load(char *fileName)
|
|||||||
void
|
void
|
||||||
AddrSpace::Execute(char* fileName)
|
AddrSpace::Execute(char* fileName)
|
||||||
{
|
{
|
||||||
|
//cerr << "AddrSpace::Execute" << endl;
|
||||||
kernel->currentThread->space = this;
|
kernel->currentThread->space = this;
|
||||||
|
|
||||||
this->InitRegisters(); // set the initial register values
|
this->InitRegisters(); // set the initial register values
|
||||||
@@ -288,6 +381,13 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pfn = pte->physicalPage;
|
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!
|
// if the pageFrame is too big, there is something really wrong!
|
||||||
// An invalid translation was loaded into the page table or TLB.
|
// 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;
|
return NoException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,28 @@
|
|||||||
|
|
||||||
#define UserStackSize 1024 // increase this as necessary!
|
#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 {
|
class AddrSpace {
|
||||||
public:
|
public:
|
||||||
AddrSpace(); // Create an address space.
|
AddrSpace(); // Create an address space.
|
||||||
@@ -40,8 +62,7 @@ class AddrSpace {
|
|||||||
ExceptionType Translate(unsigned int vaddr, unsigned int *paddr, int mode);
|
ExceptionType Translate(unsigned int vaddr, unsigned int *paddr, int mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TranslationEntry *pageTable; // Assume linear page table translation
|
TranslationEntry *pageTable;
|
||||||
// for now!
|
|
||||||
unsigned int numPages; // Number of pages in the virtual
|
unsigned int numPages; // Number of pages in the virtual
|
||||||
// address space
|
// address space
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,92 @@ ExceptionHandler(ExceptionType which)
|
|||||||
cout << "return value:" << val << endl;
|
cout << "return value:" << val << endl;
|
||||||
kernel->currentThread->Finish();
|
kernel->currentThread->Finish();
|
||||||
break;
|
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:
|
default:
|
||||||
cerr << "Unexpected system call " << type << "\n";
|
cerr << "Unexpected system call " << type << "\n";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -34,5 +36,43 @@ int SysCreate(char *filename)
|
|||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -34,6 +34,9 @@
|
|||||||
#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_PrintInt 16
|
||||||
|
|
||||||
#define SC_Add 42
|
#define SC_Add 42
|
||||||
#define SC_MSG 100
|
#define SC_MSG 100
|
||||||
|
|
||||||
@@ -177,6 +180,8 @@ int ThreadJoin(ThreadId id);
|
|||||||
*/
|
*/
|
||||||
void ThreadExit(int ExitCode);
|
void ThreadExit(int ExitCode);
|
||||||
|
|
||||||
|
void PrintInt(int number);
|
||||||
|
|
||||||
#endif /* IN_ASM */
|
#endif /* IN_ASM */
|
||||||
|
|
||||||
#endif /* SYSCALL_H */
|
#endif /* SYSCALL_H */
|
||||||
|
|||||||
7
docker-compose.yaml
Normal file
7
docker-compose.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
build: .
|
||||||
|
user: '60139:60139'
|
||||||
|
volumes:
|
||||||
|
- './:/work'
|
||||||
Reference in New Issue
Block a user