---
# System prepended metadata

title: OS lab 1 prototype
tags: [os]

---


# Trace code
##  a.
> Trace the SC_Halt system call to understand the implementation of a system call.
### Run()
當有system call是，可以看到是用OneInstrucion()一次執行一個指令，此時user program是在user mode下執行的。
```cpp=
void
Machine::Run()
{
    Instruction *instr = new Instruction;  // storage for decoded instruction
    if (debug->IsEnabled('m')) {
        cout << "Starting program in thread: " << kernel->currentThread->getName();
        cout << ", at time: " << kernel->stats->totalTicks << "\n";
    }
    kernel->interrupt->setStatus(UserMode);
    for (;;) {
        DEBUG(dbgTraCode, "In Machine::Run(), into OneInstruction " << "== Tick " << kernel->stats->totalTicks << " ==");
        OneInstruction(instr);
        DEBUG(dbgTraCode, "In Machine::Run(), return from OneInstruction  " << "== Tick " << kernel->stats->totalTicks << " ==");

        DEBUG(dbgTraCode, "In Machine::Run(), into OneTick " << "== Tick " << kernel->stats->totalTicks << " ==");
        kernel->interrupt->OneTick();
        DEBUG(dbgTraCode, "In Machine::Run(), return from OneTick " << "== Tick " << kernel->stats->totalTicks << " ==");
        if (singleStep && (runUntilTime <= kernel->stats->totalTicks))
                Debugger();
    }
}

```
### OneInstruction()
當OneInstruction()接收system call後，會跳到這段程式碼，去執行對應的操作，也就是調用RaiseException()。
```cpp=
 case OP_SYSCALL:
        DEBUG(dbgTraCode, "In Machine::OneInstruction, RaiseException(SyscallException, 0), " << kernel->stats->totalTicks);
        RaiseException(SyscallException, 0);
        return;

```
### RaiseException()
會先把發生例外的記憶體位置儲存起來，然後會先轉成system mode去處裡interrupt，之後再轉回user mode。這過程中會調用ExceptionHandler()，並傳入ExceptionType類型的參數。
```cpp=
void
Machine::RaiseException(ExceptionType which, int badVAddr)
{
    DEBUG(dbgMach, "Exception: " << exceptionNames[which]);
    registers[BadVAddrReg] = badVAddr;
    DelayedLoad(0, 0);                  // finish anything in progress
    kernel->interrupt->setStatus(SystemMode);
    ExceptionHandler(which);            // interrupts are enabled at this point
    kernel->interrupt->setStatus(UserMode);
}

```
### exception handler()
接收到的ExceptionType包含不同類型的exception，我們要看的是system call，接收exception，並判斷是否跟system call有關，是的話會根據system call類別作處理，也就是根據system call的類型調用對應的function call。
##### ExceptionType的實作
```cpp=
enum ExceptionType { NoException,           // Everything ok!
                     SyscallException,      // A program executed a system call.
                     PageFaultException,    // No valid translation found
                     ReadOnlyException,     // Write attempted to page marked
                                            // "read-only"
                     BusErrorException,     // Translation resulted in an
                                            // invalid physical address
                     AddressErrorException, // Unaligned reference or one that
                                            // was beyond the end of the
                                            // address space
                     OverflowException,     // Integer overflow in add or sub.
                     IllegalInstrException, // Unimplemented or reserved instr.

                     NumExceptionTypes
};

```
由於關注的是SC_Halt，它會呼叫SysHalt()。
```cpp
void ExceptionHandler(ExceptionType which)
{
        char ch;
        int val;
        int type = kernel->machine->ReadRegister(2);
        int status, exit, threadID, programID, fileID, numChar;
        DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
        DEBUG(dbgTraCode, "In ExceptionHandler(), Received Exception " << which << " type: " << type << ", " << kernel->stats->totalTicks);
        switch (which)
        {
        case SyscallException:
                switch (type)
                {
                case SC_Halt:
                        DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
                        SysHalt();
                        cout << "in exception\n";
                        ASSERTNOTREACHED();
                        break;
                case SC_PrintInt:
                        DEBUG(dbgSys, "Print Int\n");
                        val = kernel->machine->ReadRegister(4);
                        DEBUG(dbgTraCode, "In ExceptionHandler(), into SysPrintInt, " << kernel->stats->totalTicks);
                        SysPrintInt(val);
                        DEBUG(dbgTraCode, "In ExceptionHandler(), return from SysPrintInt, " << kernel->stats->totalTicks);
                        // Set Program Counter
                        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_MSG:
                        DEBUG(dbgSys, "Message received.\n");
                        val = kernel->machine->ReadRegister(4);
                        {
                                char *msg = &(kernel->machine->mainMemory[val]);
                                cout << msg << endl;
                        }
                        SysHalt();
                        ASSERTNOTREACHED();
                        break;
                case SC_Create:
                        val = kernel->machine->ReadRegister(4);
                        {
                                char *filename = &(kernel->machine->mainMemory[val]);
                                // cout << filename << endl;
                                status = SysCreate(filename);
                                kernel->machine->WriteRegister(2, (int)status);
                        }
                        kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
                        kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        return;
                        ASSERTNOTREACHED();
                        break;
								case SC_Add:
                        DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n");
                        /* Process SysAdd Systemcall*/
                        int result;
                        result = SysAdd(/* int op1 */ (int)kernel->machine->ReadRegister(4),
                                                        /* int op2 */ (int)kernel->machine->ReadRegister(5));
                        DEBUG(dbgSys, "Add returning with " << result << "\n");
                        /* Prepare Result */
                        kernel->machine->WriteRegister(2, (int)result);
                        /* Modify return point */
                        {
                                /* set previous programm counter (debugging only)*/
                                kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));

                                /* set programm counter to next instruction (all Instructions are 4 byte wide)*/
                                kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);

                                /* set next programm counter for brach execution */
                                kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        }
                        cout << "result is " << result << "\n";
                        return;
                        ASSERTNOTREACHED();
                        break;
								case SC_Exit:
                        DEBUG(dbgAddr, "Program exit\n");
                        val = kernel->machine->ReadRegister(4);
                        cout << "return value:" << val << endl;
                        kernel->currentThread->Finish();
                        break;
                default:
                        cerr << "Unexpected system call " << type << "\n";
                        break;
                }
                break;
        default:
                cerr << "Unexpected user mode exception " << (int)which << "\n";
                break;
        }
        ASSERTNOTREACHED();
}
```


### ksyscall.h
一個包裝用的函式，去調用interrupt的Halt()。
```cpp=
void SysHalt()
{
  kernel->interrupt->Halt();
}
```


### Halt()
把目前kernel的狀態輸出出來。透過delete kernel把所有os的功能停掉。
```cpp=
//----------------------------------------------------------------------
// Interrupt::Halt
//      Shut down Nachos cleanly, printing out performance statistics.
//----------------------------------------------------------------------
void
Interrupt::Halt()
{
    cout << "Machine halting!\n\n";
    cout << "This is halt\n";
    kernel->stats->Print();
    delete kernel;      // Never returns.
}
```
## b.
> understand basic operation and data structure in a file system。
### ExceptonHandler()
創建檔案也屬於system call的類別，在ExceptonHandler()是由SC_Create來處理的。透過呼叫SysCreate來創建檔案。

```cpp=
 case SC_Create:
                        val = kernel->machine->ReadRegister(4);
                        {
                                char *filename = &(kernel->machine->mainMemory[val]);
                                // cout << filename << endl;
                                status = SysCreate(filename);
                                kernel->machine->WriteRegister(2, (int)status);
                        }
                        kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
                        kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        return;
                        ASSERTNOTREACHED();
                        break;
```
除此之外，還會更新對應的program counter的值。透過以下操作去更新。
```cpp=
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));

/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);

/* set next programm counter for brach execution */
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
```
WriteRegister的具體實作如下。
用assert去檢查要寫入的register有沒有滿足大於等於零，而且小於等於register的總數量，這作法的概念memory protection相似，合法的話，就把value寫入register。
```cpp=
void
Machine::WriteRegister(int num, int value)
{
    ASSERT((num >= 0) && (num < NumTotalRegs));
    registers[num] = value;
}

```

### SysCreate()
呼叫fileSystem的Create()。
```cpp=
int SysCreate(char *filename)
{
	// return value
	// 1: success
	// 0: failed
	return kernel->fileSystem->Create(filename);
}
```
### Create()
先呼叫OpenForWrite，它的實作在sysdep.cc裡，之後透過回傳的fileDscriptor來判定檔案有無創建成功。在呼叫c++內建的close()關閉檔案。
```cpp=
bool Create(char *name) {
    int fileDescriptor = OpenForWrite(name);

    if (fileDescriptor == -1) return FALSE;
    Close(fileDescriptor);
    return TRUE;
}
```
 OpenForWrite的實作，基本上底層就呼叫了c++內建的open funciton。
```cpp=
int
OpenForWrite(char *name)
{
    int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);

    ASSERT(fd >= 0);
    return fd;
}

```

## c.
> Trace the SC_PrintInt system call to understand how NachOS implements
asynchronized I/O using CallBack functions and register schedule events.
### ExceptonHandler
直接呼叫SysPrintInt(val)。
```cpp=
 case SC_PrintInt:
                        DEBUG(dbgSys, "Print Int\n");
                        val = kernel->machine->ReadRegister(4);
                        DEBUG(dbgTraCode, "In ExceptionHandler(), into SysPrintInt, " << kernel->stats->totalTicks);
                        SysPrintInt(val);
                        DEBUG(dbgTraCode, "In ExceptionHandler(), return from SysPrintInt, " << kernel->stats->totalTicks);
                        // Set Program Counter
                        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;
```
### SysPrintInt()
ksycall.h的SysPrintInt直接調用synchConsoleOut的PutInt(val)
```cpp=
void SysPrintInt(int val)
{
  DEBUG(dbgTraCode, "In ksyscall.h:SysPrintInt, into synchConsoleOut->PutInt, " << kernel->stats->totalTicks);
  kernel->synchConsoleOut->PutInt(val);
  DEBUG(dbgTraCode, "In ksyscall.h:SysPrintInt, return from synchConsoleOut->PutInt, " << kernel->stats->totalTicks);
}
```

### PutInt()
一開始用sprintf把value存到str，並透過lock去綁定資源，透過idx++，我們能夠把字元一個一個讓PutChar作處理， waitFor->P()是讓還沒處理到的字元先等待，等退出while loop後再讓lock解除綁定。
```cpp=
void
SynchConsoleOutput::PutInt(int value)
{
    char str[15];
    int idx=0;
    //sprintf(str, "%d\n\0", value);  the true one
    sprintf(str, "%d\n\0", value); //simply for trace code
    lock->Acquire();
    do{
        DEBUG(dbgTraCode, "In SynchConsoleOutput::PutChar, into consoleOutput->PutChar, " << kernel->stats->totalTicks);
        consoleOutput->PutChar(str[idx]);
        DEBUG(dbgTraCode, "In SynchConsoleOutput::PutChar, return from consoleOutput->PutChar, " << kernel->stats->totalTicks);
        idx++;

        DEBUG(dbgTraCode, "In SynchConsoleOutput::PutChar, into waitFor->P(), " << kernel->stats->totalTicks);
        waitFor->P();
        DEBUG(dbgTraCode, "In SynchConsoleOutput::PutChar, return form  waitFor->P(), " << kernel->stats->totalTicks);
    } while (str[idx] != '\0');
    lock->Release();
}

```

### PutChar()
先檢查putBusy是不是false，因為我們一次只能執行一次操作，若為false，透過WriteFile把字元一個一個寫入檔案，之後呼叫Schedule()。
```cpp=
void
ConsoleOutput::PutChar(char ch)
{
    ASSERT(putBusy == FALSE);
    WriteFile(writeFileNo, &ch, sizeof(char));
    putBusy = TRUE;
    kernel->interrupt->Schedule(this, ConsoleTime, ConsoleWriteInt);
}

```
### Schedule()
透過pending這資料結構去插入interrupt，在這過程中會算出interrupt的時間，並紀錄interrupt發生時，並記錄toCall也就是callback執行的函式對象。
```cpp=
void
Interrupt::Schedule(CallBackObj *toCall, int fromNow, IntType type)
{
    int when = kernel->stats->totalTicks + fromNow;
    PendingInterrupt *toOccur = new PendingInterrupt(toCall, when, type);

    DEBUG(dbgInt, "Scheduling interrupt handler the " << intTypeNames[type] << " at time = " << when);
    ASSERT(fromNow > 0);

    pending->Insert(toOccur);
}
```
### Run()
在a.的部分已經提過了，machine會逐一執行instruction，並進到OneTick這個function。
```cpp=
kernel->interrupt->setStatus(UserMode);
    for (;;) {
        DEBUG(dbgTraCode, "In Machine::Run(), into OneInstruction " << "== Tick " << kernel->stats->totalTicks << " ==");
        OneInstruction(instr);
        DEBUG(dbgTraCode, "In Machine::Run(), return from OneInstruction  " << "== Tick " << kernel->stats->totalTicks << " ==");

        DEBUG(dbgTraCode, "In Machine::Run(), into OneTick " << "== Tick " << kernel->stats->totalTicks << " ==");
        kernel->interrupt->OneTick();
        DEBUG(dbgTraCode, "In Machine::Run(), return from OneTick " << "== Tick " << kernel->stats->totalTicks << " ==");
        if (singleStep && (runUntilTime <= kernel->stats->totalTicks))
                Debugger();
    }
```
### OneTick 
ChangelLevel會決定kernel level在一段時間內能不能接受interrupt，然後他去檢查這段時間interrupt去處理。
在檢查現在有多少interrupt等著處裡時，會先讓kernel暫時不能接收interrupt，等到檢查完後，才會重新開啟，這段時間會去呼叫checkifdue()去處理interrupt。可以看到底層維護timer的時間。
以下是ChangeLevel()的實作。
```cpp=
void
Interrupt::ChangeLevel(IntStatus old, IntStatus now)
{
    level = now;
    DEBUG(dbgInt, "\tinterrupts: " << intLevelNames[old] << " -> " << intLevelNames[now]);
}

```
以下是OneTick()的實作。

```cpp=
void
Interrupt::OneTick()
{
    MachineStatus oldStatus = status;
    Statistics *stats = kernel->stats;

// advance simulated time
    if (status == SystemMode) {
        stats->totalTicks += SystemTick;
        stats->systemTicks += SystemTick;
    } else {
        stats->totalTicks += UserTick;
        stats->userTicks += UserTick;
    }
    DEBUG(dbgInt, "== Tick " << stats->totalTicks << " ==");

// check any pending interrupts are now ready to fire
    ChangeLevel(IntOn, IntOff); // first, turn off interrupts
                                // (interrupt handlers run with
                                // interrupts disabled)
    CheckIfDue(FALSE);          // check for pending interrupts
    ChangeLevel(IntOff, IntOn); // re-enable interrupts
    if (yieldOnReturn) {        // if the timer device handler asked
                                // for a context switch, ok to do it now
        yieldOnReturn = FALSE;
        status = SystemMode;            // yield is a kernel routine
        kernel->currentThread->Yield();
        status = oldStatus;
    }
}
```
### checkifdue()
pending存放著待處理的interrupt，在這段程式碼中，它會去檢查interrupt有沒有如期執行完，有的話，return true，否則return false。
```cpp=
bool
Interrupt::CheckIfDue(bool advanceClock)
{
    PendingInterrupt *next;
    Statistics *stats = kernel->stats;

    ASSERT(level == IntOff);            // interrupts need to be disabled,
                                        // to invoke an interrupt handler
    if (debug->IsEnabled(dbgInt)) {
        DumpState();
    }
    if (pending->IsEmpty()) {           // no pending interrupts
        return FALSE;
    }
    next = pending->Front();
		if (next->when > stats->totalTicks) {
        if (!advanceClock) {            // not time yet
            return FALSE;
        }
        else {                  // advance the clock to next interrupt
            stats->idleTicks += (next->when - stats->totalTicks);
            stats->totalTicks = next->when;
            // UDelay(1000L); // rcgood - to stop nachos from spinning.
        }
    }

    DEBUG(dbgInt, "Invoking interrupt handler for the ");
    DEBUG(dbgInt, intTypeNames[next->type] << " at time " << next->when);

    if (kernel->machine != NULL) {
        kernel->machine->DelayedLoad(0, 0);
    }

    inHandler = TRUE;
    do {
        next = pending->RemoveFront();    // pull interrupt off list
                DEBUG(dbgTraCode, "In Interrupt::CheckIfDue, into callOnInterrupt->CallBack, " << stats->totalTicks);
        next->callOnInterrupt->CallBack();// call the interrupt handler
                DEBUG(dbgTraCode, "In Interrupt::CheckIfDue, return from callOnInterrupt->CallBack, " << stats->totalTicks);
        delete next;
    } while (!pending->IsEmpty()
                && (pending->Front()->when <= stats->totalTicks));
    inHandler = FALSE;
		return TRUE;
}
```
### ConsoleOutput::CallBack()
更新putBusy的狀態，更新numConsoleCharsWritten，呼叫SynchConsoleOutput::CallBack()。
```cpp=
void
ConsoleOutput::CallBack()
{
    DEBUG(dbgTraCode, "In ConsoleOutput::CallBack(), " << kernel->stats->totalTicks);
    putBusy = FALSE;
    kernel->stats->numConsoleCharsWritten++;
    callWhenDone->CallBack();
}

```
### SynchConsoleOutput::CallBack()
呼叫waitFor->V()。
```cpp=
void
SynchConsoleOutput::CallBack()
{
    DEBUG(dbgTraCode, "In SynchConsoleOutput::CallBack(), " << kernel->stats->totalTicks);
    waitFor->V();
}

```
## d. //TODO
> Trace the Makefile in code/test/Makefile to understand how test files are compiled
```cmake=
include Makefile.dep

CC = $(GCCDIR)gcc
AS = $(GCCDIR)as
LD = $(GCCDIR)ld

INCDIR =-I../userprog -I../lib
CFLAGS = -g -G 0 -c $(INCDIR) -B/usr/bin/local/nachos/lib/gcc-lib/decstation-ultrix/2.95.2/ -B/usr/bin/local/nachos/decstation-ultrix/bin/

ifeq ($(hosttype),unknown)
PROGRAMS = unknownhost
else
# change this if you create a new test program!
#PROGRAMS = add halt shell matmult sort segments test1 test2 a
PROGRAMS = add halt createFile fileIO_test1 fileIO_test2 LotOfAdd
endif

all: $(PROGRAMS)

start.o: start.S ../userprog/syscall.h
        $(CC) $(CFLAGS) $(ASFLAGS) -c start.S

halt.o: halt.c
halt: halt.o start.o
        $(LD) $(LDFLAGS) start.o halt.o -o halt.coff
        $(COFF2NOFF) halt.coff halt

add.o: add.c
        $(CC) $(CFLAGS) -c add.c

add: add.o start.o
        $(LD) $(LDFLAGS) start.o add.o -o add.coff
        $(COFF2NOFF) add.coff add

LotOfAdd.o: LotOfAdd.c
        $(CC) $(CFLAGS) -c LotOfAdd.c

LotOfAdd: LotOfAdd.o start.o
        $(LD) $(LDFLAGS) start.o LotOfAdd.o -o LotOfAdd.coff
        $(COFF2NOFF) LotOfAdd.coff LotOfAdd

shell.o: shell.c
        $(CC) $(CFLAGS) -c shell.c
shell: shell.o start.o
        $(LD) $(LDFLAGS) start.o shell.o -o shell.coff
        $(COFF2NOFF) shell.coff shell

sort.o: sort.c
        $(CC) $(CFLAGS) -c sort.c
sort: sort.o start.o
        $(LD) $(LDFLAGS) start.o sort.o -o sort.coff
        $(COFF2NOFF) sort.coff sort

segments.o: segments.c
        $(CC) $(CFLAGS) -c segments.c
segments: segments.o start.o
        $(LD) $(LDFLAGS) start.o segments.o -o segments.coff
        $(COFF2NOFF) segments.coff segments

matmult.o: matmult.c
        $(CC) $(CFLAGS) -c matmult.c
matmult: matmult.o start.o
        $(LD) $(LDFLAGS) start.o matmult.o -o matmult.coff
        $(COFF2NOFF) matmult.coff matmult
consoleIO_test1.o: consoleIO_test1.c
        $(CC) $(CFLAGS) -c consoleIO_test1.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
        $(CC) $(CFLAGS) -c consoleIO_test2.c
consoleIO_test2: consoleIO_test2.o start.o
        $(LD) $(LDFLAGS) start.o consoleIO_test2.o -o consoleIO_test2.coff
        $(COFF2NOFF) consoleIO_test2.coff consoleIO_test2

consoleIO_test3.o: consoleIO_test3.c
        $(CC) $(CFLAGS) -c consoleIO_test3.c
consoleIO_test3: consoleIO_test3.o start.o
        $(LD) $(LDFLAGS) start.o consoleIO_test3.o -o consoleIO_test3.coff
        $(COFF2NOFF) consoleIO_test3.coff consoleIO_test3

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


createFile.o: createFile.c
        $(CC) $(CFLAGS) -c createFile.c
createFile: createFile.o start.o
        $(LD) $(LDFLAGS) start.o createFile.o -o createFile.coff
        $(COFF2NOFF) createFile.coff createFile
clean:
        $(RM) -f *.o *.ii
        $(RM) -f *.coff

distclean: clean
        $(RM) -f $(PROGRAMS)

unknownhost:
        @echo Host type could not be determined.
        @echo make is terminating.
        @echo If you are on an MFCF machine, contact the instructor to report this problem
        @echo Otherwise, edit Makefile.dep and try again.
```
# Implementation 

進到syscall.h，把//刪除。
```cpp=
#define SC_Open 6
#define SC_Read 7
#define SC_Write 8
#define SC_Close 10

```
在到exception handler去新增SC_Open，SC_Read，SC_WriteSC_Close
```cpp=
case SC_Create:
                        val = kernel->machine->ReadRegister(4);
                        {
                                char *filename = &(kernel->machine->mainMemory[val]);
                                // cout << filename << endl;
                                status = SysCreate(filename);
                                kernel->machine->WriteRegister(2, (int)status);
                        }
                        kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
                        kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
                        return;
                        ASSERTNOTREACHED();
                        break;
```
看到SysCreate，應該要去fileSystem改。
```cpp=

int SysCreate(char *filename)
{
        // return value
        // 1: success
        // 0: failed
        return kernel->fileSystem->Create(filename);
}

```
因為ksyscall.h只是調用kernel的function call，所以就照著寫，在fileSystem有對應的函數可以用，就呼叫它們。
```cpp=
OpenFileId SysOpen(char *filename)
{
        return kernel->fileSystem->OpenAFile(filename);
}
int SysWrite(char *buffer, int size, OpenFileId id)
{
        return kernel->fileSystem->WriteFile(buffer, size, id);
}

int SysRead(char *buffer, int size, OpenFileId id)
{
        return kernel->fileSystem->ReadFile(buffer, size, id);
}

int SysClose(OpenFileId id)
{
        return kernel->fileSystem->CloseFile(id);
}

```