Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
72320ede22
|
|||
| 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,18 +200,18 @@ 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 $(INCPATH) $(DEFINES) $(HOSTCFLAGS) -DCHANGED -m32 -w
|
||||||
LDFLAGS = -m32
|
LDFLAGS = -m32
|
||||||
CPP_AS_FLAGS= -m32
|
CPP_AS_FLAGS= -m32
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
CPP=/lib/cpp
|
CPP=/lib/cpp
|
||||||
CC = g++ -m32 -Wno-deprecated
|
CC = g++ -m32
|
||||||
LD = g++ -m32 -Wno-deprecated
|
LD = g++ -m32
|
||||||
AS = as --32
|
AS = as --32
|
||||||
RM = /bin/rm
|
RM = /bin/rm
|
||||||
|
|
||||||
INCPATH = -I../network -I../filesys -I../userprog -I../threads -I../machine -I../lib -I-
|
INCPATH = -iquote../network -iquote../filesys -iquote../userprog -iquote../threads -iquote../machine -iquote../lib
|
||||||
|
|
||||||
PROGRAM = nachos
|
PROGRAM = nachos
|
||||||
|
|
||||||
|
|||||||
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.
@@ -40,13 +40,15 @@
|
|||||||
#ifdef FILESYS_STUB // Temporarily implement file system calls as
|
#ifdef FILESYS_STUB // Temporarily implement file system calls as
|
||||||
// calls to UNIX, until the real file system
|
// calls to UNIX, until the real file system
|
||||||
// implementation is available
|
// implementation is available
|
||||||
|
|
||||||
|
typedef int OpenFileId;
|
||||||
|
|
||||||
class FileSystem {
|
class FileSystem {
|
||||||
public:
|
public:
|
||||||
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;
|
||||||
@@ -54,11 +56,60 @@ class FileSystem {
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpenFileId OpenFiles(char* name) {
|
||||||
|
OpenFile* file = Open(name);
|
||||||
|
if (!file) return -1;
|
||||||
|
int freeIndex = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
if (!fileDescriptorTable[i])
|
||||||
|
freeIndex = i;
|
||||||
|
|
||||||
|
if (freeIndex == -1)
|
||||||
|
return -1;
|
||||||
|
OpenFileId fileDescriptor = file->GetFileDescriptor();
|
||||||
|
fileDescriptorTable[freeIndex] = file;
|
||||||
|
return fileDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WriteFile(char* buffer, int size, OpenFileId fd) {
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
if (!fileDescriptorTable[i])
|
||||||
|
continue;
|
||||||
|
if (fileDescriptorTable[i]->GetFileDescriptor() == fd) {
|
||||||
|
return fileDescriptorTable[i]->Write(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadFile(char* buffer, int size, OpenFileId fd) {
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
if (!fileDescriptorTable[i])
|
||||||
|
continue;
|
||||||
|
if (fileDescriptorTable[i]->GetFileDescriptor() == fd)
|
||||||
|
return fileDescriptorTable[i]->Read(buffer, size);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CloseFile(OpenFileId fd) {
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
if (!fileDescriptorTable[i])
|
||||||
|
continue;
|
||||||
|
if (fileDescriptorTable[i]->GetFileDescriptor() == fd) {
|
||||||
|
delete fileDescriptorTable[i];
|
||||||
|
fileDescriptorTable[i] = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool Remove(char* name) { return Unlink(name) == 0; }
|
bool Remove(char* name) { return Unlink(name) == 0; }
|
||||||
|
|
||||||
OpenFile* fileDescriptorTable[20];
|
OpenFile* fileDescriptorTable[20];
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
#ifdef FILESYS_STUB // Temporarily implement calls to
|
#ifdef FILESYS_STUB // Temporarily implement calls to
|
||||||
// Nachos file system as calls to UNIX!
|
// Nachos file system as calls to UNIX!
|
||||||
// See definitions listed under #else
|
// See definitions listed under #else
|
||||||
|
typedef int OpenFileId;
|
||||||
|
|
||||||
class OpenFile {
|
class OpenFile {
|
||||||
public:
|
public:
|
||||||
OpenFile(int f) { file = f; currentOffset = 0; } // open the file
|
OpenFile(int f) { file = f; currentOffset = 0; } // open the file
|
||||||
@@ -54,6 +56,10 @@ class OpenFile {
|
|||||||
|
|
||||||
int Length() { Lseek(file, 0, 2); return Tell(file); }
|
int Length() { Lseek(file, 0, 2); return Tell(file); }
|
||||||
|
|
||||||
|
OpenFileId GetFileDescriptor() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int file;
|
int file;
|
||||||
int currentOffset;
|
int currentOffset;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ const char dbgFile = 'f'; // file system
|
|||||||
const char dbgAddr = 'a'; // address spaces
|
const char dbgAddr = 'a'; // address spaces
|
||||||
const char dbgNet = 'n'; // network emulation
|
const char dbgNet = 'n'; // network emulation
|
||||||
const char dbgSys = 'u'; // systemcall
|
const char dbgSys = 'u'; // systemcall
|
||||||
|
const char dbgSche = 'z';
|
||||||
|
|
||||||
class Debug {
|
class Debug {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -172,3 +172,19 @@ ConsoleOutput::PutChar(char ch)
|
|||||||
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
|
kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// ConsoleOutput::PutInt()
|
||||||
|
// Write a int to the simulated display, schedule an interrupt
|
||||||
|
// to occur in the future, and return.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
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,9 @@ 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 value);
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "copyright.h"
|
#include "copyright.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
|
#include "synchconsole.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
// String definitions for debugging messages
|
// String definitions for debugging messages
|
||||||
@@ -359,3 +360,31 @@ Interrupt::DumpState()
|
|||||||
cout << "\nEnd of pending interrupts\n";
|
cout << "\nEnd of pending interrupts\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Interrupt::PrintInt(int value)
|
||||||
|
{
|
||||||
|
kernel->synchConsoleOut->PutInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenFileId
|
||||||
|
Interrupt::OpenFile(char *filename)
|
||||||
|
{
|
||||||
|
return kernel->fileSystem->OpenFiles(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Interrupt::WriteFile(char *buffer, int size, OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->fileSystem->WriteFile(buffer, size, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Interrupt::CloseFile(OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->fileSystem->CloseFile(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Interrupt::ReadFile(char *buffer, int size, OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->fileSystem->ReadFile(buffer, size, fd);
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
|
|
||||||
|
#include "filesys.h"
|
||||||
|
|
||||||
|
typedef int OpenFileId;
|
||||||
|
|
||||||
// Interrupts can be disabled (IntOff) or enabled (IntOn)
|
// Interrupts can be disabled (IntOff) or enabled (IntOn)
|
||||||
enum IntStatus { IntOff, IntOn };
|
enum IntStatus { IntOff, IntOn };
|
||||||
|
|
||||||
@@ -48,8 +52,10 @@ enum MachineStatus {IdleMode, SystemMode, UserMode};
|
|||||||
// IntType records which hardware device generated an interrupt.
|
// IntType records which hardware device generated an interrupt.
|
||||||
// In Nachos, we support a hardware timer device, a disk, a console
|
// In Nachos, we support a hardware timer device, a disk, a console
|
||||||
// display and keyboard, and a network.
|
// display and keyboard, and a network.
|
||||||
enum IntType { TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
|
enum IntType {
|
||||||
NetworkSendInt, NetworkRecvInt};
|
TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
|
||||||
|
NetworkSendInt, NetworkRecvInt
|
||||||
|
};
|
||||||
|
|
||||||
// The following class defines an interrupt that is scheduled
|
// The following class defines an interrupt that is scheduled
|
||||||
// to occur in the future. The internal data structures are
|
// to occur in the future. The internal data structures are
|
||||||
@@ -96,6 +102,10 @@ class Interrupt {
|
|||||||
|
|
||||||
void PrintInt(int number);
|
void PrintInt(int number);
|
||||||
int CreateFile(char* filename);
|
int CreateFile(char* filename);
|
||||||
|
OpenFileId OpenFile(char* filename);
|
||||||
|
int WriteFile(char* buffer, int size, OpenFileId fd);
|
||||||
|
int CloseFile(OpenFileId fd);
|
||||||
|
int ReadFile(char* buffer, int size, OpenFileId fd);
|
||||||
|
|
||||||
void YieldOnReturn(); // cause a context switch on return
|
void YieldOnReturn(); // cause a context switch on return
|
||||||
// from an interrupt handler
|
// from an interrupt handler
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ enum ExceptionType { NoException, // Everything ok!
|
|||||||
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, // Insufficient memory
|
||||||
|
|
||||||
NumExceptionTypes
|
NumExceptionTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ const int UserTick = 1; // advance for each user-level instruction
|
|||||||
const int SystemTick = 10; // advance each time interrupts are enabled
|
const int SystemTick = 10; // advance each time interrupts are enabled
|
||||||
const int RotationTime = 500; // time disk takes to rotate one sector
|
const int RotationTime = 500; // time disk takes to rotate one sector
|
||||||
const int SeekTime = 500; // time disk takes to seek past one track
|
const int SeekTime = 500; // time disk takes to seek past one track
|
||||||
const int ConsoleTime = 100; // time to read or write one character
|
|
||||||
|
// MP4 MODIFIED
|
||||||
|
const int ConsoleTime = 1; // time to read or write one character
|
||||||
|
|
||||||
const int NetworkTime = 100; // time to send or receive one packet
|
const int NetworkTime = 100; // time to send or receive one packet
|
||||||
const int TimerTicks = 100; // (average) time between timer interrupts
|
const int TimerTicks = 100; // (average) time between timer interrupts
|
||||||
|
|
||||||
|
|||||||
@@ -107,13 +107,13 @@ 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 = mp4_consoleIO_1 mp4_consoleIO_2 mp4_consoleIO_3 mp4_consoleIO_4
|
||||||
PROGRAMS = halt
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
@@ -121,72 +121,34 @@ all: $(PROGRAMS)
|
|||||||
start.o: start.S ../userprog/syscall.h
|
start.o: start.S ../userprog/syscall.h
|
||||||
$(CC) $(CFLAGS) $(ASFLAGS) -c start.S
|
$(CC) $(CFLAGS) $(ASFLAGS) -c start.S
|
||||||
|
|
||||||
halt.o: halt.c
|
mp4_consoleIO_1.o: mp4_consoleIO_1.c
|
||||||
$(CC) $(CFLAGS) -c halt.c
|
$(CC) $(CFLAGS) -c mp4_consoleIO_1.c
|
||||||
halt: halt.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o halt.o -o halt.coff
|
|
||||||
$(COFF2NOFF) halt.coff halt
|
|
||||||
|
|
||||||
add.o: add.c
|
mp4_consoleIO_1: mp4_consoleIO_1.o start.o
|
||||||
$(CC) $(CFLAGS) -c add.c
|
$(LD) $(LDFLAGS) start.o mp4_consoleIO_1.o -o mp4_consoleIO_1.coff
|
||||||
|
$(COFF2NOFF) mp4_consoleIO_1.coff mp4_consoleIO_1
|
||||||
|
|
||||||
add: add.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o add.o -o add.coff
|
|
||||||
$(COFF2NOFF) add.coff add
|
|
||||||
|
|
||||||
shell.o: shell.c
|
mp4_consoleIO_2.o: mp4_consoleIO_2.c
|
||||||
$(CC) $(CFLAGS) -c shell.c
|
$(CC) $(CFLAGS) -c mp4_consoleIO_2.c
|
||||||
shell: shell.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o shell.o -o shell.coff
|
|
||||||
$(COFF2NOFF) shell.coff shell
|
|
||||||
|
|
||||||
sort.o: sort.c
|
mp4_consoleIO_2: mp4_consoleIO_2.o start.o
|
||||||
$(CC) $(CFLAGS) -c sort.c
|
$(LD) $(LDFLAGS) start.o mp4_consoleIO_2.o -o mp4_consoleIO_2.coff
|
||||||
sort: sort.o start.o
|
$(COFF2NOFF) mp4_consoleIO_2.coff mp4_consoleIO_2
|
||||||
$(LD) $(LDFLAGS) start.o sort.o -o sort.coff
|
|
||||||
$(COFF2NOFF) sort.coff sort
|
|
||||||
|
|
||||||
segments.o: segments.c
|
mp4_consoleIO_3.o: mp4_consoleIO_3.c
|
||||||
$(CC) $(CFLAGS) -c segments.c
|
$(CC) $(CFLAGS) -c mp4_consoleIO_3.c
|
||||||
segments: segments.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o segments.o -o segments.coff
|
|
||||||
$(COFF2NOFF) segments.coff segments
|
|
||||||
|
|
||||||
matmult.o: matmult.c
|
mp4_consoleIO_3: mp4_consoleIO_3.o start.o
|
||||||
$(CC) $(CFLAGS) -c matmult.c
|
$(LD) $(LDFLAGS) start.o mp4_consoleIO_3.o -o mp4_consoleIO_3.coff
|
||||||
matmult: matmult.o start.o
|
$(COFF2NOFF) mp4_consoleIO_3.coff mp4_consoleIO_3
|
||||||
$(LD) $(LDFLAGS) start.o matmult.o -o matmult.coff
|
|
||||||
$(COFF2NOFF) matmult.coff matmult
|
|
||||||
|
|
||||||
consoleIO_test1.o: consoleIO_test1.c
|
mp4_consoleIO_4.o: mp4_consoleIO_4.c
|
||||||
$(CC) $(CFLAGS) -c consoleIO_test1.c
|
$(CC) $(CFLAGS) -c mp4_consoleIO_4.c
|
||||||
consoleIO_test1: consoleIO_test1.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o consoleIO_test1.o -o consoleIO_test1.coff
|
|
||||||
$(COFF2NOFF) consoleIO_test1.coff consoleIO_test1
|
|
||||||
|
|
||||||
consoleIO_test2.o: consoleIO_test2.c
|
mp4_consoleIO_4: mp4_consoleIO_4.o start.o
|
||||||
$(CC) $(CFLAGS) -c consoleIO_test2.c
|
$(LD) $(LDFLAGS) start.o mp4_consoleIO_4.o -o mp4_consoleIO_4.coff
|
||||||
consoleIO_test2: consoleIO_test2.o start.o
|
$(COFF2NOFF) mp4_consoleIO_4.coff mp4_consoleIO_4
|
||||||
$(LD) $(LDFLAGS) start.o consoleIO_test2.o -o consoleIO_test2.coff
|
|
||||||
$(COFF2NOFF) consoleIO_test2.coff consoleIO_test2
|
|
||||||
|
|
||||||
fileIO_test1.o: fileIO_test1.c
|
|
||||||
$(CC) $(CFLAGS) -c fileIO_test1.c
|
|
||||||
fileIO_test1: fileIO_test1.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o fileIO_test1.o -o fileIO_test1.coff
|
|
||||||
$(COFF2NOFF) fileIO_test1.coff fileIO_test1
|
|
||||||
|
|
||||||
fileIO_test2.o: fileIO_test2.c
|
|
||||||
$(CC) $(CFLAGS) -c fileIO_test2.c
|
|
||||||
fileIO_test2: fileIO_test2.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o fileIO_test2.o -o fileIO_test2.coff
|
|
||||||
$(COFF2NOFF) fileIO_test2.coff fileIO_test2
|
|
||||||
|
|
||||||
fileIO_test3.o: fileIO_test3.c
|
|
||||||
$(CC) $(CFLAGS) -c fileIO_test3.c
|
|
||||||
fileIO_test3: fileIO_test3.o start.o
|
|
||||||
$(LD) $(LDFLAGS) start.o fileIO_test3.o -o fileIO_test3.coff
|
|
||||||
$(COFF2NOFF) fileIO_test3.coff fileIO_test3
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@@ -196,6 +158,13 @@ clean:
|
|||||||
distclean: clean
|
distclean: clean
|
||||||
$(RM) -f $(PROGRAMS)
|
$(RM) -f $(PROGRAMS)
|
||||||
|
|
||||||
|
run: $(PROGRAMS)
|
||||||
|
timeout 1 $(NACHOS) -ep mp4_consoleIO_1 70 -ep mp4_consoleIO_3 80 -ep mp4_consoleIO_2 50
|
||||||
|
echo 'done'
|
||||||
|
|
||||||
|
debug: $(PROGRAMS)
|
||||||
|
timeout 1 $(NACHOS) -d z -ep mp4_consoleIO_1 60 -ep mp4_consoleIO_2 70
|
||||||
|
|
||||||
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.
10
code/test/mp4_consoleIO_1.c
Normal file
10
code/test/mp4_consoleIO_1.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 4; n++) {
|
||||||
|
PrintInt(1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
code/test/mp4_consoleIO_2.c
Normal file
9
code/test/mp4_consoleIO_2.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 5; n++) {
|
||||||
|
PrintInt(2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
10
code/test/mp4_consoleIO_3.c
Normal file
10
code/test/mp4_consoleIO_3.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 12; n++) {
|
||||||
|
PrintInt(3);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
code/test/mp4_consoleIO_4.c
Normal file
9
code/test/mp4_consoleIO_4.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 11; n++) {
|
||||||
|
PrintInt(4);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
make clean
|
make distclean
|
||||||
make
|
make
|
||||||
../build.linux/nachos -e halt
|
rm -f *.o *.ii
|
||||||
|
rm -f *.coff
|
||||||
|
echo "=========================="
|
||||||
|
timeout 1 ../build.linux/nachos -e mp4_consoleIO_1 -e mp4_consoleIO_2
|
||||||
|
echo "=========================="
|
||||||
|
timeout 1 ../build.linux/nachos -e mp4_consoleIO_3 -e mp4_consoleIO_4
|
||||||
|
echo "done"
|
||||||
@@ -58,6 +58,14 @@ MSG:
|
|||||||
j $31
|
j $31
|
||||||
.end MSG
|
.end MSG
|
||||||
|
|
||||||
|
.globl PrintInt
|
||||||
|
.ent PrintInt
|
||||||
|
PrintInt:
|
||||||
|
addiu $2,$0,SC_PrintInt
|
||||||
|
syscall
|
||||||
|
j $31
|
||||||
|
.end PrintInt
|
||||||
|
|
||||||
.globl Add
|
.globl Add
|
||||||
.ent Add
|
.ent Add
|
||||||
Add:
|
Add:
|
||||||
|
|||||||
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);
|
||||||
|
}
|
||||||
@@ -49,7 +49,9 @@ Alarm::CallBack()
|
|||||||
Interrupt* interrupt = kernel->interrupt;
|
Interrupt* interrupt = kernel->interrupt;
|
||||||
MachineStatus status = interrupt->getStatus();
|
MachineStatus status = interrupt->getStatus();
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
if (status != IdleMode) {
|
if (status != IdleMode) {
|
||||||
interrupt->YieldOnReturn();
|
// interrupt->YieldOnReturn();
|
||||||
}
|
}
|
||||||
|
// ---------
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,32 +43,48 @@ Kernel::Kernel(int argc, char **argv)
|
|||||||
// number generator
|
// number generator
|
||||||
randomSlice = TRUE;
|
randomSlice = TRUE;
|
||||||
i++;
|
i++;
|
||||||
} else if (strcmp(argv[i], "-s") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-s") == 0) {
|
||||||
debugUserProg = TRUE;
|
debugUserProg = TRUE;
|
||||||
} else if (strcmp(argv[i], "-e") == 0) {
|
}
|
||||||
|
// Todo ----
|
||||||
|
else if (strcmp(argv[i], "-e") == 0) {
|
||||||
execfile[++execfileNum] = argv[++i];
|
execfile[++execfileNum] = argv[++i];
|
||||||
cout << execfile[execfileNum] << "\n";
|
cout << execfile[execfileNum] << "\n";
|
||||||
} else if (strcmp(argv[i], "-ci") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-ep") == 0) {
|
||||||
|
execfile[++execfileNum] = argv[++i];
|
||||||
|
execPriority[execfileNum] = atoi(argv[++i]);
|
||||||
|
cout << execfile[execfileNum] << " with priority "
|
||||||
|
<< execPriority[execfileNum] << "\n";
|
||||||
|
}
|
||||||
|
// ---------
|
||||||
|
else if (strcmp(argv[i], "-ci") == 0) {
|
||||||
ASSERT(i + 1 < argc);
|
ASSERT(i + 1 < argc);
|
||||||
consoleIn = argv[i + 1];
|
consoleIn = argv[i + 1];
|
||||||
i++;
|
i++;
|
||||||
} else if (strcmp(argv[i], "-co") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-co") == 0) {
|
||||||
ASSERT(i + 1 < argc);
|
ASSERT(i + 1 < argc);
|
||||||
consoleOut = argv[i + 1];
|
consoleOut = argv[i + 1];
|
||||||
i++;
|
i++;
|
||||||
#ifndef FILESYS_STUB
|
#ifndef FILESYS_STUB
|
||||||
} else if (strcmp(argv[i], "-f") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-f") == 0) {
|
||||||
formatFlag = TRUE;
|
formatFlag = TRUE;
|
||||||
#endif
|
#endif
|
||||||
} else if (strcmp(argv[i], "-n") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-n") == 0) {
|
||||||
ASSERT(i + 1 < argc); // next argument is float
|
ASSERT(i + 1 < argc); // next argument is float
|
||||||
reliability = atof(argv[i + 1]);
|
reliability = atof(argv[i + 1]);
|
||||||
i++;
|
i++;
|
||||||
} else if (strcmp(argv[i], "-m") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-m") == 0) {
|
||||||
ASSERT(i + 1 < argc); // next argument is int
|
ASSERT(i + 1 < argc); // next argument is int
|
||||||
hostName = atoi(argv[i + 1]);
|
hostName = atoi(argv[i + 1]);
|
||||||
i++;
|
i++;
|
||||||
} else if (strcmp(argv[i], "-u") == 0) {
|
}
|
||||||
|
else if (strcmp(argv[i], "-u") == 0) {
|
||||||
cout << "Partial usage: nachos [-rs randomSeed]\n";
|
cout << "Partial usage: nachos [-rs randomSeed]\n";
|
||||||
cout << "Partial usage: nachos [-s]\n";
|
cout << "Partial usage: nachos [-s]\n";
|
||||||
cout << "Partial usage: nachos [-ci consoleIn] [-co consoleOut]\n";
|
cout << "Partial usage: nachos [-ci consoleIn] [-co consoleOut]\n";
|
||||||
@@ -111,9 +127,12 @@ Kernel::Initialize()
|
|||||||
#else
|
#else
|
||||||
fileSystem = new FileSystem(formatFlag);
|
fileSystem = new FileSystem(formatFlag);
|
||||||
#endif // FILESYS_STUB
|
#endif // FILESYS_STUB
|
||||||
postOfficeIn = new PostOfficeInput(10);
|
|
||||||
postOfficeOut = new PostOfficeOutput(reliability);
|
|
||||||
|
|
||||||
|
// MP4 MODIFIED
|
||||||
|
// postOfficeIn = new PostOfficeInput(10);
|
||||||
|
// postOfficeOut = new PostOfficeOutput(reliability);
|
||||||
|
|
||||||
|
frameTable = new FrameTable();
|
||||||
interrupt->Enable();
|
interrupt->Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +152,12 @@ Kernel::~Kernel()
|
|||||||
delete synchConsoleOut;
|
delete synchConsoleOut;
|
||||||
delete synchDisk;
|
delete synchDisk;
|
||||||
delete fileSystem;
|
delete fileSystem;
|
||||||
delete postOfficeIn;
|
|
||||||
delete postOfficeOut;
|
// MP4 MODIFIED
|
||||||
|
// delete postOfficeIn;
|
||||||
|
// delete postOfficeOut;
|
||||||
|
|
||||||
|
delete frameTable;
|
||||||
|
|
||||||
Exit(0);
|
Exit(0);
|
||||||
}
|
}
|
||||||
@@ -261,16 +284,18 @@ void ForkExecute(Thread *t)
|
|||||||
void Kernel::ExecAll()
|
void Kernel::ExecAll()
|
||||||
{
|
{
|
||||||
for (int i = 1;i <= execfileNum;i++) {
|
for (int i = 1;i <= execfileNum;i++) {
|
||||||
int a = Exec(execfile[i]);
|
int a = Exec(execfile[i], execPriority[i]);
|
||||||
}
|
}
|
||||||
currentThread->Finish();
|
currentThread->Finish();
|
||||||
//Kernel::Exec();
|
//Kernel::Exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
int Kernel::Exec(char* name)
|
int Kernel::Exec(char* name, int priority)
|
||||||
{
|
{
|
||||||
t[threadNum] = new Thread(name, threadNum);
|
t[threadNum] = new Thread(name, threadNum);
|
||||||
|
t[threadNum]->setPriority(priority);
|
||||||
|
// ---------
|
||||||
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++;
|
threadNum++;
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ class SynchConsoleInput;
|
|||||||
class SynchConsoleOutput;
|
class SynchConsoleOutput;
|
||||||
class SynchDisk;
|
class SynchDisk;
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
|
// ---------
|
||||||
|
|
||||||
class Kernel {
|
class Kernel {
|
||||||
public:
|
public:
|
||||||
@@ -37,7 +38,11 @@ class Kernel {
|
|||||||
// 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);
|
|
||||||
|
// Todo ----
|
||||||
|
int Exec(char* name, int priority);
|
||||||
|
// ---------
|
||||||
|
|
||||||
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
|
||||||
@@ -61,13 +66,18 @@ class Kernel {
|
|||||||
FileSystem *fileSystem;
|
FileSystem *fileSystem;
|
||||||
PostOfficeInput *postOfficeIn;
|
PostOfficeInput *postOfficeIn;
|
||||||
PostOfficeOutput *postOfficeOut;
|
PostOfficeOutput *postOfficeOut;
|
||||||
|
FrameTable *frameTable;
|
||||||
int hostName; // machine identifier
|
int hostName; // machine identifier
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Thread* t[10];
|
Thread* t[10];
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
char* execfile[10];
|
char* execfile[10];
|
||||||
|
int execPriority[10];
|
||||||
|
// ---------
|
||||||
|
|
||||||
int execfileNum;
|
int execfileNum;
|
||||||
int threadNum;
|
int threadNum;
|
||||||
bool randomSlice; // enable pseudo-random time slicing
|
bool randomSlice; // enable pseudo-random time slicing
|
||||||
@@ -82,5 +92,3 @@ class Kernel {
|
|||||||
|
|
||||||
|
|
||||||
#endif // KERNEL_H
|
#endif // KERNEL_H
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Scheduler::Scheduler
|
// Scheduler::Scheduler
|
||||||
@@ -29,9 +30,20 @@
|
|||||||
// Initially, no ready threads.
|
// Initially, no ready threads.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
|
|
||||||
|
int cmp(Thread *a, Thread *b)
|
||||||
|
{
|
||||||
|
int ap = a->getPriority();
|
||||||
|
int bp = b->getPriority();
|
||||||
|
return (ap < bp) - (ap > bp);
|
||||||
|
}
|
||||||
|
|
||||||
Scheduler::Scheduler()
|
Scheduler::Scheduler()
|
||||||
{
|
{
|
||||||
readyList = new List<Thread *>;
|
readyList = new SortedList(cmp);
|
||||||
|
// ---------
|
||||||
|
|
||||||
toBeDestroyed = NULL;
|
toBeDestroyed = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +72,9 @@ Scheduler::ReadyToRun (Thread *thread)
|
|||||||
DEBUG(dbgThread, "Putting thread on ready list: " << thread->getName());
|
DEBUG(dbgThread, "Putting thread on ready list: " << thread->getName());
|
||||||
//cout << "Putting thread on ready list: " << thread->getName() << endl ;
|
//cout << "Putting thread on ready list: " << thread->getName() << endl ;
|
||||||
thread->setStatus(READY);
|
thread->setStatus(READY);
|
||||||
readyList->Append(thread);
|
|
||||||
|
DEBUG(dbgSche, "[A] Tick [" << kernel->stats->totalTicks << "]: Process [" << thread->getName() << "] is inserted into queue.");
|
||||||
|
readyList->Insert(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@@ -78,7 +92,9 @@ Scheduler::FindNextToRun ()
|
|||||||
|
|
||||||
if (readyList->IsEmpty()) {
|
if (readyList->IsEmpty()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
DEBUG(dbgSche, "[B] Tick [" << kernel->stats->totalTicks << "]: Process [" << readyList->Front()->getName() << "] is removed from queue.");
|
||||||
return readyList->RemoveFront();
|
return readyList->RemoveFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +140,7 @@ Scheduler::Run (Thread *nextThread, bool finishing)
|
|||||||
nextThread->setStatus(RUNNING); // nextThread is now running
|
nextThread->setStatus(RUNNING); // nextThread is now running
|
||||||
|
|
||||||
DEBUG(dbgThread, "Switching from: " << oldThread->getName() << " to: " << nextThread->getName());
|
DEBUG(dbgThread, "Switching from: " << oldThread->getName() << " to: " << nextThread->getName());
|
||||||
|
DEBUG(dbgSche, "[C] Tick [" << kernel->stats->totalTicks << "]: Process [" << nextThread->getName() << "] is now selected for execution, thread [" << oldThread->getName() << "] is replaced.");
|
||||||
|
|
||||||
// This is a machine-dependent assembly language routine defined
|
// This is a machine-dependent assembly language routine defined
|
||||||
// in switch.s. You may have to think
|
// in switch.s. You may have to think
|
||||||
|
|||||||
@@ -35,8 +35,11 @@ class Scheduler {
|
|||||||
// SelfTest for scheduler is implemented in class Thread
|
// SelfTest for scheduler is implemented in class Thread
|
||||||
|
|
||||||
private:
|
private:
|
||||||
List<Thread *> *readyList; // queue of threads that are ready to run,
|
// Todo ----
|
||||||
|
SortedList<Thread *> *readyList; // queue of threads that are ready to run,
|
||||||
// but not running
|
// but not running
|
||||||
|
// ---------
|
||||||
|
|
||||||
Thread *toBeDestroyed; // finishing thread to be destroyed
|
Thread *toBeDestroyed; // finishing thread to be destroyed
|
||||||
// by the next thread that runs
|
// by the next thread that runs
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ Thread::Thread(char* threadName, int threadID)
|
|||||||
stackTop = NULL;
|
stackTop = NULL;
|
||||||
stack = NULL;
|
stack = NULL;
|
||||||
status = JUST_CREATED;
|
status = JUST_CREATED;
|
||||||
for (int i = 0; i < MachineStateSize; i++) {
|
for (int i = 0; i < MachineStateSize; i++)
|
||||||
|
{
|
||||||
machineState[i] = NULL; // not strictly necessary, since
|
machineState[i] = NULL; // not strictly necessary, since
|
||||||
// new thread ignores contents
|
// new thread ignores contents
|
||||||
// of machine registers
|
// of machine registers
|
||||||
@@ -88,8 +89,7 @@ Thread::~Thread()
|
|||||||
// "arg" is a single argument to be passed to the procedure.
|
// "arg" is a single argument to be passed to the procedure.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::Fork(VoidFunctionPtr func, void *arg)
|
||||||
Thread::Fork(VoidFunctionPtr func, void *arg)
|
|
||||||
{
|
{
|
||||||
Interrupt *interrupt = kernel->interrupt;
|
Interrupt *interrupt = kernel->interrupt;
|
||||||
Scheduler *scheduler = kernel->scheduler;
|
Scheduler *scheduler = kernel->scheduler;
|
||||||
@@ -119,10 +119,10 @@ Thread::Fork(VoidFunctionPtr func, void *arg)
|
|||||||
// Don't do this: void foo() { int bigArray[10000]; ... }
|
// Don't do this: void foo() { int bigArray[10000]; ... }
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::CheckOverflow()
|
||||||
Thread::CheckOverflow()
|
{
|
||||||
|
if (stack != NULL)
|
||||||
{
|
{
|
||||||
if (stack != NULL) {
|
|
||||||
#ifdef HPUX // Stacks grow upward on the Snakes
|
#ifdef HPUX // Stacks grow upward on the Snakes
|
||||||
ASSERT(stack[StackSize - 1] == STACK_FENCEPOST);
|
ASSERT(stack[StackSize - 1] == STACK_FENCEPOST);
|
||||||
#else
|
#else
|
||||||
@@ -142,8 +142,7 @@ Thread::CheckOverflow()
|
|||||||
// 2. enable interrupts (so we can get time-sliced)
|
// 2. enable interrupts (so we can get time-sliced)
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::Begin()
|
||||||
Thread::Begin ()
|
|
||||||
{
|
{
|
||||||
ASSERT(this == kernel->currentThread);
|
ASSERT(this == kernel->currentThread);
|
||||||
DEBUG(dbgThread, "Beginning thread: " << name);
|
DEBUG(dbgThread, "Beginning thread: " << name);
|
||||||
@@ -167,8 +166,7 @@ Thread::Begin ()
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
//
|
//
|
||||||
void
|
void Thread::Finish()
|
||||||
Thread::Finish ()
|
|
||||||
{
|
{
|
||||||
(void)kernel->interrupt->SetLevel(IntOff);
|
(void)kernel->interrupt->SetLevel(IntOff);
|
||||||
ASSERT(this == kernel->currentThread);
|
ASSERT(this == kernel->currentThread);
|
||||||
@@ -178,7 +176,6 @@ Thread::Finish ()
|
|||||||
// not reached
|
// not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Thread::Yield
|
// Thread::Yield
|
||||||
// Relinquish the CPU if any other thread is ready to run.
|
// Relinquish the CPU if any other thread is ready to run.
|
||||||
@@ -197,8 +194,7 @@ Thread::Finish ()
|
|||||||
// Similar to Thread::Sleep(), but a little different.
|
// Similar to Thread::Sleep(), but a little different.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::Yield()
|
||||||
Thread::Yield ()
|
|
||||||
{
|
{
|
||||||
Thread *nextThread;
|
Thread *nextThread;
|
||||||
IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);
|
IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);
|
||||||
@@ -208,7 +204,8 @@ Thread::Yield ()
|
|||||||
DEBUG(dbgThread, "Yielding thread: " << name);
|
DEBUG(dbgThread, "Yielding thread: " << name);
|
||||||
|
|
||||||
nextThread = kernel->scheduler->FindNextToRun();
|
nextThread = kernel->scheduler->FindNextToRun();
|
||||||
if (nextThread != NULL) {
|
if (nextThread != NULL)
|
||||||
|
{
|
||||||
kernel->scheduler->ReadyToRun(this);
|
kernel->scheduler->ReadyToRun(this);
|
||||||
kernel->scheduler->Run(nextThread, FALSE);
|
kernel->scheduler->Run(nextThread, FALSE);
|
||||||
}
|
}
|
||||||
@@ -235,8 +232,7 @@ Thread::Yield ()
|
|||||||
// so that there can't be a time slice between pulling the first thread
|
// so that there can't be a time slice between pulling the first thread
|
||||||
// off the ready list, and switching to it.
|
// off the ready list, and switching to it.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void
|
void Thread::Sleep(bool finishing)
|
||||||
Thread::Sleep (bool finishing)
|
|
||||||
{
|
{
|
||||||
Thread *nextThread;
|
Thread *nextThread;
|
||||||
|
|
||||||
@@ -247,7 +243,8 @@ Thread::Sleep (bool finishing)
|
|||||||
|
|
||||||
status = BLOCKED;
|
status = BLOCKED;
|
||||||
// cout << "debug Thread::Sleep " << name << "wait for Idle\n";
|
// cout << "debug Thread::Sleep " << name << "wait for Idle\n";
|
||||||
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL) {
|
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL)
|
||||||
|
{
|
||||||
kernel->interrupt->Idle(); // no one to run, wait for an interrupt
|
kernel->interrupt->Idle(); // no one to run, wait for an interrupt
|
||||||
}
|
}
|
||||||
// returns when it's time for us to run
|
// returns when it's time for us to run
|
||||||
@@ -279,11 +276,14 @@ PLabelToAddr(void *plabel)
|
|||||||
{
|
{
|
||||||
int funcPtr = (int)plabel;
|
int funcPtr = (int)plabel;
|
||||||
|
|
||||||
if (funcPtr & 0x02) {
|
if (funcPtr & 0x02)
|
||||||
|
{
|
||||||
// L-Field is set. This is a PLT pointer
|
// L-Field is set. This is a PLT pointer
|
||||||
funcPtr -= 2; // Get rid of the L bit
|
funcPtr -= 2; // Get rid of the L bit
|
||||||
return (*(void **)funcPtr);
|
return (*(void **)funcPtr);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// L-field not set.
|
// L-field not set.
|
||||||
return plabel;
|
return plabel;
|
||||||
}
|
}
|
||||||
@@ -302,8 +302,7 @@ PLabelToAddr(void *plabel)
|
|||||||
// "arg" is the parameter to be passed to the procedure
|
// "arg" is the parameter to be passed to the procedure
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::StackAllocate(VoidFunctionPtr func, void *arg)
|
||||||
Thread::StackAllocate (VoidFunctionPtr func, void *arg)
|
|
||||||
{
|
{
|
||||||
stack = (int *)AllocBoundedArray(StackSize * sizeof(int));
|
stack = (int *)AllocBoundedArray(StackSize * sizeof(int));
|
||||||
|
|
||||||
@@ -336,7 +335,6 @@ Thread::StackAllocate (VoidFunctionPtr func, void *arg)
|
|||||||
*stack = STACK_FENCEPOST;
|
*stack = STACK_FENCEPOST;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef x86
|
#ifdef x86
|
||||||
// the x86 passes the return address on the stack. In order for SWITCH()
|
// the x86 passes the return address on the stack. In order for SWITCH()
|
||||||
// to go to ThreadRoot when we switch to this thread, the return addres
|
// to go to ThreadRoot when we switch to this thread, the return addres
|
||||||
@@ -372,8 +370,7 @@ Thread::StackAllocate (VoidFunctionPtr func, void *arg)
|
|||||||
// while executing kernel code. This routine saves the former.
|
// while executing kernel code. This routine saves the former.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::SaveUserState()
|
||||||
Thread::SaveUserState()
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NumTotalRegs; i++)
|
for (int i = 0; i < NumTotalRegs; i++)
|
||||||
userRegisters[i] = kernel->machine->ReadRegister(i);
|
userRegisters[i] = kernel->machine->ReadRegister(i);
|
||||||
@@ -388,14 +385,12 @@ Thread::SaveUserState()
|
|||||||
// while executing kernel code. This routine restores the former.
|
// while executing kernel code. This routine restores the former.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::RestoreUserState()
|
||||||
Thread::RestoreUserState()
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NumTotalRegs; i++)
|
for (int i = 0; i < NumTotalRegs; i++)
|
||||||
kernel->machine->WriteRegister(i, userRegisters[i]);
|
kernel->machine->WriteRegister(i, userRegisters[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// SimpleThread
|
// SimpleThread
|
||||||
// Loop 5 times, yielding the CPU to another ready thread
|
// Loop 5 times, yielding the CPU to another ready thread
|
||||||
@@ -410,7 +405,8 @@ SimpleThread(int which)
|
|||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
for (num = 0; num < 5; num++) {
|
for (num = 0; num < 5; num++)
|
||||||
|
{
|
||||||
cout << "*** thread " << which << " looped " << num << " times\n";
|
cout << "*** thread " << which << " looped " << num << " times\n";
|
||||||
kernel->currentThread->Yield();
|
kernel->currentThread->Yield();
|
||||||
}
|
}
|
||||||
@@ -422,8 +418,7 @@ SimpleThread(int which)
|
|||||||
// to call SimpleThread, and then calling SimpleThread ourselves.
|
// to call SimpleThread, and then calling SimpleThread ourselves.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void Thread::SelfTest()
|
||||||
Thread::SelfTest()
|
|
||||||
{
|
{
|
||||||
DEBUG(dbgThread, "Entering Thread::SelfTest");
|
DEBUG(dbgThread, "Entering Thread::SelfTest");
|
||||||
|
|
||||||
@@ -433,3 +428,16 @@ Thread::SelfTest()
|
|||||||
kernel->currentThread->Yield();
|
kernel->currentThread->Yield();
|
||||||
SimpleThread(0);
|
SimpleThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
|
int Thread::getPriority() const
|
||||||
|
{
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::setPriority(int p)
|
||||||
|
{
|
||||||
|
ASSERT(p >= 0 && p <= 149);
|
||||||
|
priority = p;
|
||||||
|
}
|
||||||
|
// ---------
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ class Thread {
|
|||||||
int *stackTop; // the current stack pointer
|
int *stackTop; // the current stack pointer
|
||||||
void *machineState[MachineStateSize]; // all registers except for stackTop
|
void *machineState[MachineStateSize]; // all registers except for stackTop
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
|
int priority;
|
||||||
|
// ---------
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Thread(char* debugName, int threadID); // initialize a Thread
|
Thread(char* debugName, int threadID); // initialize a Thread
|
||||||
~Thread(); // deallocate a Thread
|
~Thread(); // deallocate a Thread
|
||||||
@@ -89,6 +93,11 @@ class Thread {
|
|||||||
|
|
||||||
// basic thread operations
|
// basic thread operations
|
||||||
|
|
||||||
|
// Todo ----
|
||||||
|
int getPriority() const;
|
||||||
|
void setPriority(int p);
|
||||||
|
// ---------
|
||||||
|
|
||||||
void Fork(VoidFunctionPtr func, void *arg);
|
void Fork(VoidFunctionPtr func, void *arg);
|
||||||
// Make thread run (*func)(arg)
|
// Make thread run (*func)(arg)
|
||||||
void Yield(); // Relinquish the CPU if any
|
void Yield(); // Relinquish the CPU if any
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
// object file header, in case the file was generated on a little
|
// object file header, in case the file was generated on a little
|
||||||
// endian machine, and we're now running on a big endian machine.
|
// endian machine, and we're now running on a big endian machine.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SwapHeader(NoffHeader* noffH)
|
SwapHeader(NoffHeader* noffH)
|
||||||
{
|
{
|
||||||
@@ -64,9 +63,10 @@ SwapHeader (NoffHeader *noffH)
|
|||||||
// memory. For now, this is really simple (1:1), since we are
|
// memory. For now, this is really simple (1:1), since we are
|
||||||
// only uniprogramming, and we have a single unsegmented page table
|
// only uniprogramming, and we have a single unsegmented page table
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
AddrSpace::AddrSpace()
|
AddrSpace::AddrSpace()
|
||||||
{
|
{
|
||||||
|
pageTable = NULL; // initialize with NULL
|
||||||
|
/*
|
||||||
pageTable = new TranslationEntry[NumPhysPages];
|
pageTable = new TranslationEntry[NumPhysPages];
|
||||||
for (int i = 0; i < NumPhysPages; i++) {
|
for (int i = 0; i < NumPhysPages; i++) {
|
||||||
pageTable[i].virtualPage = i; // for now, virt page # = phys page #
|
pageTable[i].virtualPage = i; // for now, virt page # = phys page #
|
||||||
@@ -79,6 +79,7 @@ AddrSpace::AddrSpace()
|
|||||||
|
|
||||||
// zero out the entire address space
|
// zero out the entire address space
|
||||||
bzero(kernel->machine->mainMemory, MemorySize);
|
bzero(kernel->machine->mainMemory, MemorySize);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@@ -88,7 +89,9 @@ AddrSpace::AddrSpace()
|
|||||||
|
|
||||||
AddrSpace::~AddrSpace()
|
AddrSpace::~AddrSpace()
|
||||||
{
|
{
|
||||||
delete pageTable;
|
/* delete pageTable; */
|
||||||
|
// release frame table by page table
|
||||||
|
kernel->frameTable->Release(pageTable, numPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -101,7 +104,6 @@ AddrSpace::~AddrSpace()
|
|||||||
//
|
//
|
||||||
// "fileName" is the file containing the object code to load into memory
|
// "fileName" is the file containing the object code to load into memory
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AddrSpace::Load(char* fileName)
|
AddrSpace::Load(char* fileName)
|
||||||
{
|
{
|
||||||
@@ -135,37 +137,102 @@ AddrSpace::Load(char *fileName)
|
|||||||
numPages = divRoundUp(size, PageSize);
|
numPages = divRoundUp(size, PageSize);
|
||||||
size = numPages * PageSize;
|
size = numPages * PageSize;
|
||||||
|
|
||||||
ASSERT(numPages <= NumPhysPages); // check we're not trying
|
pageTable = kernel->frameTable->Allocate(numPages);
|
||||||
// to run anything too big --
|
if (!pageTable) {
|
||||||
// at least until we have
|
kernel->interrupt->setStatus(SystemMode);
|
||||||
// virtual memory
|
ExceptionHandler(MemoryLimitException);
|
||||||
|
kernel->interrupt->setStatus(UserMode);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
uint paddr; // physical address
|
||||||
|
ExceptionType ex; // occurring exception
|
||||||
|
int sz, // total size to load
|
||||||
|
vaddr, // base virtual address
|
||||||
|
fpos, // base file position
|
||||||
|
to_load; // size to load on each time
|
||||||
|
|
||||||
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);
|
||||||
executable->ReadAt(
|
|
||||||
&(kernel->machine->mainMemory[noffH.code.virtualAddr]),
|
sz = noffH.code.size;
|
||||||
noffH.code.size, noffH.code.inFileAddr);
|
vaddr = noffH.code.virtualAddr;
|
||||||
|
fpos = noffH.code.inFileAddr;
|
||||||
|
|
||||||
|
for (uint offset = 0; offset < sz; offset += PageSize) {
|
||||||
|
ex = Translate(vaddr + offset, &paddr, 1);
|
||||||
|
|
||||||
|
if (ex != NoException) {
|
||||||
|
kernel->interrupt->setStatus(SystemMode);
|
||||||
|
ExceptionHandler(ex);
|
||||||
|
kernel->interrupt->setStatus(UserMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_load = offset + PageSize < sz ? PageSize : sz - offset;
|
||||||
|
|
||||||
|
executable->ReadAt(
|
||||||
|
&(kernel->machine->mainMemory[paddr]),
|
||||||
|
to_load, fpos + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
sz = noffH.initData.size;
|
||||||
|
vaddr = noffH.initData.virtualAddr;
|
||||||
|
fpos = noffH.initData.inFileAddr;
|
||||||
|
|
||||||
|
for (uint offset = 0; offset < sz; offset += PageSize) {
|
||||||
|
ex = Translate(vaddr + offset, &paddr, 1);
|
||||||
|
|
||||||
|
if (ex != NoException) {
|
||||||
|
kernel->interrupt->setStatus(SystemMode);
|
||||||
|
ExceptionHandler(ex);
|
||||||
|
kernel->interrupt->setStatus(UserMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
to_load = offset + PageSize < sz ? PageSize : sz - offset;
|
||||||
|
|
||||||
executable->ReadAt(
|
executable->ReadAt(
|
||||||
&(kernel->machine->mainMemory[noffH.initData.virtualAddr]),
|
&(kernel->machine->mainMemory[paddr]),
|
||||||
noffH.initData.size, noffH.initData.inFileAddr);
|
to_load, fpos + offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#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);
|
||||||
|
|
||||||
|
sz = noffH.readonlyData.size;
|
||||||
|
vaddr = noffH.readonlyData.virtualAddr;
|
||||||
|
fpos = noffH.readonlyData.inFileAddr;
|
||||||
|
|
||||||
|
// read only flag for page table
|
||||||
|
for (int i = 0, lim = divRoundUp(sz, PageSize),
|
||||||
|
from = vaddr / PageSize; i < lim; ++i)
|
||||||
|
pageTable[from + i].readOnly = TRUE;
|
||||||
|
|
||||||
|
for (uint offset = 0; offset < sz; offset += PageSize) {
|
||||||
|
ex = Translate(vaddr + offset, &paddr, 0); // read only
|
||||||
|
|
||||||
|
if (ex != NoException) {
|
||||||
|
kernel->interrupt->setStatus(SystemMode);
|
||||||
|
ExceptionHandler(ex);
|
||||||
|
kernel->interrupt->setStatus(UserMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
to_load = offset + PageSize < sz ? PageSize : sz - offset;
|
||||||
|
|
||||||
executable->ReadAt(
|
executable->ReadAt(
|
||||||
&(kernel->machine->mainMemory[noffH.readonlyData.virtualAddr]),
|
&(kernel->machine->mainMemory[paddr]),
|
||||||
noffH.readonlyData.size, noffH.readonlyData.inFileAddr);
|
to_load, fpos + offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -181,7 +248,6 @@ AddrSpace::Load(char *fileName)
|
|||||||
// the address space
|
// the address space
|
||||||
//
|
//
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
AddrSpace::Execute(char* fileName)
|
AddrSpace::Execute(char* fileName)
|
||||||
{
|
{
|
||||||
@@ -191,7 +257,7 @@ AddrSpace::Execute(char* fileName)
|
|||||||
this->InitRegisters(); // set the initial register values
|
this->InitRegisters(); // set the initial register values
|
||||||
this->RestoreState(); // load page table register
|
this->RestoreState(); // load page table register
|
||||||
|
|
||||||
kernel->machine->Run(); // jump to the user progam
|
kernel->machine->Run(); // jump to the user program
|
||||||
|
|
||||||
ASSERTNOTREACHED(); // machine->Run never returns;
|
ASSERTNOTREACHED(); // machine->Run never returns;
|
||||||
// the address space exits
|
// the address space exits
|
||||||
@@ -208,7 +274,6 @@ AddrSpace::Execute(char* fileName)
|
|||||||
// will be saved/restored into the currentThread->userRegisters
|
// will be saved/restored into the currentThread->userRegisters
|
||||||
// when this thread is context switched out.
|
// when this thread is context switched out.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
AddrSpace::InitRegisters()
|
AddrSpace::InitRegisters()
|
||||||
{
|
{
|
||||||
@@ -242,9 +307,9 @@ AddrSpace::InitRegisters()
|
|||||||
//
|
//
|
||||||
// For now, don't need to save anything!
|
// For now, don't need to save anything!
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void AddrSpace::SaveState()
|
void AddrSpace::SaveState()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// AddrSpace::RestoreState
|
// AddrSpace::RestoreState
|
||||||
@@ -253,7 +318,6 @@ void AddrSpace::SaveState()
|
|||||||
//
|
//
|
||||||
// For now, tell the machine where to find the page table.
|
// For now, tell the machine where to find the page table.
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
void AddrSpace::RestoreState()
|
void AddrSpace::RestoreState()
|
||||||
{
|
{
|
||||||
kernel->machine->pageTable = pageTable;
|
kernel->machine->pageTable = pageTable;
|
||||||
@@ -311,6 +375,43 @@ AddrSpace::Translate(unsigned int vaddr, unsigned int *paddr, int isReadWrite)
|
|||||||
return NoException;
|
return NoException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameTable::FrameTable() {
|
||||||
|
for (int i = 0; i < NumPhysPages; ++i)
|
||||||
|
available.Append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameTable::~FrameTable() {}
|
||||||
|
|
||||||
|
uint FrameTable::RemainSize() { return available.NumInList(); }
|
||||||
|
|
||||||
|
PageTable FrameTable::Allocate(uint pageNum) {
|
||||||
|
// if not enough memory
|
||||||
|
if (RemainSize() < pageNum)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PageTable ptb = new TranslationEntry[pageNum];
|
||||||
|
|
||||||
|
for (int i = 0; i < pageNum; ++i) {
|
||||||
|
ptb[i].virtualPage = i;
|
||||||
|
int f = available.RemoveFront(); // frame number
|
||||||
|
ptb[i].physicalPage = f;
|
||||||
|
// initialize flags
|
||||||
|
ptb[i].valid = TRUE;
|
||||||
|
ptb[i].use = FALSE;
|
||||||
|
ptb[i].dirty = FALSE;
|
||||||
|
ptb[i].readOnly = FALSE;
|
||||||
|
// zero out the entire address space
|
||||||
|
bzero(kernel->machine->mainMemory + f * PageSize, PageSize);
|
||||||
|
}
|
||||||
|
return ptb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameTable::Release(PageTable ptb, int pageNum) {
|
||||||
|
if (!ptb)
|
||||||
|
return; // nothing to release
|
||||||
|
for (int i = 0; i < pageNum; ++i)
|
||||||
|
available.Append(ptb[i].physicalPage);
|
||||||
|
delete[] ptb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,3 +51,51 @@ class AddrSpace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // ADDRSPACE_H
|
#endif // ADDRSPACE_H
|
||||||
|
|
||||||
|
#ifndef FRAME_TABLE_H
|
||||||
|
#define FRAME_TABLE_H
|
||||||
|
|
||||||
|
#include "machine.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure of Virtual Memory
|
||||||
|
*/
|
||||||
|
typedef TranslationEntry* PageTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure of Physical Memory
|
||||||
|
*/
|
||||||
|
class FrameTable {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Initialize a frame table
|
||||||
|
*/
|
||||||
|
FrameTable();
|
||||||
|
~FrameTable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate pageNum of frames (pages) and collect
|
||||||
|
* corresponding translation information into a page table.
|
||||||
|
*
|
||||||
|
* @param pageNum numbers of pages
|
||||||
|
* @return a new Page table, NULL if not enough memory space
|
||||||
|
*/
|
||||||
|
PageTable Allocate(uint pageNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the physical memory frame
|
||||||
|
* which the info stored in PageTable
|
||||||
|
*/
|
||||||
|
void Release(PageTable ptb, int pageNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the remaining numbers of entry of the frame table
|
||||||
|
*/
|
||||||
|
uint RemainSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
List<int> available;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAME_TABLE_H */
|
||||||
@@ -54,6 +54,7 @@ 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;
|
||||||
|
int fd, size;
|
||||||
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case SyscallException:
|
case SyscallException:
|
||||||
@@ -74,6 +75,13 @@ ExceptionHandler(ExceptionType which)
|
|||||||
SysHalt();
|
SysHalt();
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
|
case SC_PrintInt:
|
||||||
|
val = 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;
|
||||||
case SC_Create:
|
case SC_Create:
|
||||||
val = kernel->machine->ReadRegister(4);
|
val = kernel->machine->ReadRegister(4);
|
||||||
{
|
{
|
||||||
@@ -88,6 +96,62 @@ ExceptionHandler(ExceptionType which)
|
|||||||
return;
|
return;
|
||||||
ASSERTNOTREACHED();
|
ASSERTNOTREACHED();
|
||||||
break;
|
break;
|
||||||
|
case SC_Open:
|
||||||
|
val = kernel->machine->ReadRegister(4);
|
||||||
|
{
|
||||||
|
char* filename = &(kernel->machine->mainMemory[val]);
|
||||||
|
//cout << filename << endl;
|
||||||
|
fd = SysOpen(filename);
|
||||||
|
kernel->machine->WriteRegister(2, (int)fd);
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
val = kernel->machine->ReadRegister(4);
|
||||||
|
size = kernel->machine->ReadRegister(5);
|
||||||
|
fd = kernel->machine->ReadRegister(6);
|
||||||
|
{
|
||||||
|
char* buffer = &(kernel->machine->mainMemory[val]);
|
||||||
|
size = SysWrite(buffer, size, fd);
|
||||||
|
kernel->machine->WriteRegister(2, (int)size);
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
fd = kernel->machine->ReadRegister(4);
|
||||||
|
{
|
||||||
|
val = SysClose(fd);
|
||||||
|
kernel->machine->WriteRegister(2, (int)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_Read:
|
||||||
|
val = kernel->machine->ReadRegister(4);
|
||||||
|
size = kernel->machine->ReadRegister(5);
|
||||||
|
fd = kernel->machine->ReadRegister(6);
|
||||||
|
{
|
||||||
|
char* buffer = &(kernel->machine->mainMemory[val]);
|
||||||
|
size = SysRead(buffer, size, fd);
|
||||||
|
kernel->machine->WriteRegister(2, (int)size);
|
||||||
|
}
|
||||||
|
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:
|
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*/
|
||||||
|
|||||||
11
code/userprog/hw4_consoleIO_1.c
Normal file
11
code/userprog/hw4_consoleIO_1.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 4; n++) {
|
||||||
|
PrintInt(1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11
code/userprog/hw4_consoleIO_2.c
Normal file
11
code/userprog/hw4_consoleIO_2.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 5; n++) {
|
||||||
|
PrintInt(2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
12
code/userprog/hw4_consoleIO_3.c
Normal file
12
code/userprog/hw4_consoleIO_3.c
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < 12; n++) {
|
||||||
|
PrintInt(3);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
12
code/userprog/hw4_consoleIO_4.c
Normal file
12
code/userprog/hw4_consoleIO_4.c
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < 11; n++) {
|
||||||
|
PrintInt(4);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "synchconsole.h"
|
#include "synchconsole.h"
|
||||||
|
|
||||||
|
typedef int OpenFileId;
|
||||||
|
|
||||||
void SysHalt()
|
void SysHalt()
|
||||||
{
|
{
|
||||||
@@ -34,5 +35,37 @@ int SysCreate(char *filename)
|
|||||||
return kernel->interrupt->CreateFile(filename);
|
return kernel->interrupt->CreateFile(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SysPrintInt(int value)
|
||||||
|
{
|
||||||
|
kernel->interrupt->PrintInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -1: open fail
|
||||||
|
// fd
|
||||||
|
OpenFileId SysOpen(char* filename)
|
||||||
|
{
|
||||||
|
return kernel->interrupt->OpenFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -1: write fail
|
||||||
|
// size
|
||||||
|
int SysWrite(char* buffer, int size, OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->interrupt->WriteFile(buffer, size, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1: close success
|
||||||
|
// 0: close fail
|
||||||
|
int SysClose(OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->interrupt->CloseFile(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -1: read fail
|
||||||
|
// size
|
||||||
|
int SysRead(char* buffer, int size, OpenFileId fd)
|
||||||
|
{
|
||||||
|
return kernel->interrupt->ReadFile(buffer, size, fd);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
#endif /* ! __USERPROG_KSYSCALL_H__ */
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define NOFFMAGIC 0xbadfad /* magic number denoting Nachos
|
#define NOFFMAGIC 0xbadfad /* magic number denoting Nachos
|
||||||
* object code file
|
/* object code file*/
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct segment {
|
typedef struct segment {
|
||||||
int virtualAddr; /* location of segment in virt addr space */
|
int virtualAddr; /* location of segment in virt addr space */
|
||||||
|
|||||||
@@ -106,6 +106,20 @@ SynchConsoleOutput::PutChar(char ch)
|
|||||||
lock->Release();
|
lock->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// SynchConsoleOutput::PutInt
|
||||||
|
// Write a int to the console display, waiting if necessary.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#define SC_ThreadJoin 15
|
#define SC_ThreadJoin 15
|
||||||
#define SC_Add 42
|
#define SC_Add 42
|
||||||
#define SC_MSG 100
|
#define SC_MSG 100
|
||||||
|
#define SC_PrintInt 16
|
||||||
|
|
||||||
#ifndef IN_ASM
|
#ifndef IN_ASM
|
||||||
|
|
||||||
@@ -52,6 +53,11 @@
|
|||||||
/* Stop Nachos, and print out performance stats */
|
/* Stop Nachos, and print out performance stats */
|
||||||
void Halt();
|
void Halt();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show the int value on console
|
||||||
|
*/
|
||||||
|
void PrintInt(int value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the two operants and return the result
|
* Add the two operants and return the result
|
||||||
*/
|
*/
|
||||||
|
|||||||
7
docker-compose.yaml
Normal file
7
docker-compose.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
build: .
|
||||||
|
user: ytshih
|
||||||
|
volumes:
|
||||||
|
- './:/work'
|
||||||
Reference in New Issue
Block a user