This commit is contained in:
施羿廷
2024-10-04 19:53:08 +00:00
parent 0284b75ab6
commit ba9ef819ba
59 changed files with 419 additions and 193 deletions

View File

@@ -1,18 +1,18 @@
// exception.cc
// Entry point into the Nachos kernel from user programs.
// There are two kinds of things that can cause control to
// transfer back to here from user code:
// Entry point into the Nachos kernel from user programs.
// There are two kinds of things that can cause control to
// transfer back to here from user code:
//
// syscall -- The user code explicitly requests to call a procedure
// in the Nachos kernel. Right now, the only function we support is
// "Halt".
// syscall -- The user code explicitly requests to call a procedure
// in the Nachos kernel. Right now, the only function we support is
// "Halt".
//
// exceptions -- The user code does something that the CPU can't handle.
// For instance, accessing memory that doesn't exist, arithmetic errors,
// etc.
// exceptions -- The user code does something that the CPU can't handle.
// For instance, accessing memory that doesn't exist, arithmetic errors,
// etc.
//
// Interrupts (which can also cause control to transfer from user
// code into the Nachos kernel) are handled elsewhere.
// Interrupts (which can also cause control to transfer from user
// code into the Nachos kernel) are handled elsewhere.
//
// For now, this only handles the Halt() system call.
// Everything else core dumps.
@@ -27,106 +27,192 @@
#include "ksyscall.h"
//----------------------------------------------------------------------
// ExceptionHandler
// Entry point into the Nachos kernel. Called when a user program
// is executing, and either does a syscall, or generates an addressing
// or arithmetic exception.
// Entry point into the Nachos kernel. Called when a user program
// is executing, and either does a syscall, or generates an addressing
// or arithmetic exception.
//
// For system calls, the following is the calling convention:
// For system calls, the following is the calling convention:
//
// system call code -- r2
// arg1 -- r4
// arg2 -- r5
// arg3 -- r6
// arg4 -- r7
// system call code -- r2
// arg1 -- r4
// arg2 -- r5
// arg3 -- r6
// arg4 -- r7
//
// The result of the system call, if any, must be put back into r2.
// The result of the system call, if any, must be put back into r2.
//
// If you are handling a system call, don't forget to increment the pc
// before returning. (Or else you'll loop making the same system call forever!)
//
// "which" is the kind of exception. The list of possible exceptions
// is in machine.h.
// "which" is the kind of exception. The list of possible exceptions
// is in machine.h.
//----------------------------------------------------------------------
void
ExceptionHandler(ExceptionType which)
{
int type = kernel->machine->ReadRegister(2);
int val;
int status, exit, threadID, programID;
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
switch (which) {
int type = kernel->machine->ReadRegister(2);
int val;
int status, exit, threadID, programID;
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
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_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();
switch(type) {
case SC_Halt:
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
SysHalt();
cout<<"in exception\n";
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;
case SC_PrintInt:
DEBUG(dbgAddr, "Printing int\n");
val = (int)kernel->machine->ReadRegister(4);
SysPrintInt(val);
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Open:
DEBUG(dbgAddr, "Open file\n");
{
val = kernel->machine->ReadRegister(4);
char *name = &(kernel->machine->mainMemory[val]);
OpenFileId ret = SysOpen(name);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Read:
DEBUG(dbgAddr, "Read file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
int ret = SysRead(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Write:
DEBUG(dbgAddr, "Write file\n");
{
val = kernel->machine->ReadRegister(4);
char *buffer = &(kernel->machine->mainMemory[val]);
int size = kernel->machine->ReadRegister(5);
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(6);
// fprintf(stderr, "buffer: %p\n", buffer);
// cerr << "size: " << size << endl;
// cerr << "id: " << id << endl;
int ret = SysWrite(buffer, size, id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
case SC_Close:
DEBUG(dbgAddr, "Close file\n");
{
OpenFileId id = (OpenFileId)kernel->machine->ReadRegister(4);
int ret = SysClose(id);
kernel->machine->WriteRegister(2, ret);
}
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
return;
ASSERTNOTREACHED();
break;
default:
cerr << "Unexpected system call " << type << "\n";
break;
}
break;
default:
cerr << "Unexpected user mode exception " << (int)which << "\n";
break;
}
ASSERTNOTREACHED();
}

View File

@@ -1,38 +1,104 @@
/**************************************************************
*
* userprog/ksyscall.h
*
* Kernel interface for systemcalls
*
* by Marcus Voelp (c) Universitaet Karlsruhe
*
**************************************************************/
#ifndef __USERPROG_KSYSCALL_H__
#define __USERPROG_KSYSCALL_H__
#include "kernel.h"
#include "synchconsole.h"
void SysHalt()
{
kernel->interrupt->Halt();
}
int SysAdd(int op1, int op2)
{
return op1 + op2;
}
int SysCreate(char *filename)
{
// return value
// 1: success
// 0: failed
return kernel->interrupt->CreateFile(filename);
}
#endif /* ! __USERPROG_KSYSCALL_H__ */
/**************************************************************
*
* userprog/ksyscall.h
*
* Kernel interface for systemcalls
*
* by Marcus Voelp (c) Universitaet Karlsruhe
*
**************************************************************/
#ifndef __USERPROG_KSYSCALL_H__
#define __USERPROG_KSYSCALL_H__
#define INT_BUF_LENGTH 13
#include "kernel.h"
#include "synchconsole.h"
void SysHalt()
{
kernel->interrupt->Halt();
}
int SysAdd(int op1, int op2)
{
return op1 + op2;
}
int SysCreate(char *filename)
{
// return value
// 1: success
// 0: failed
return kernel->interrupt->CreateFile(filename);
}
void SysPrintInt(int value) {
static char zero[2] = "0";
if (value == 0) {
kernel->synchConsoleOut->PutString(zero);
return;
}
char outputBuf[INT_BUF_LENGTH];
bool isNeg = false;
int curPos = INT_BUF_LENGTH;
outputBuf[--curPos] = '\0';
outputBuf[--curPos] = '\n';
if (value < 0) {
isNeg = true;
value = -value;
}
while (value > 0) {
outputBuf[--curPos] = '0' + (value % 10);
value /= 10;
}
if (isNeg)
outputBuf[--curPos] = '-';
kernel->synchConsoleOut->PutString(&outputBuf[curPos]);
}
OpenFileId SysOpen(char *name) {
OpenFileId id = -1;
for (int i = 0; i < 20; i++)
if (kernel->fileSystem->fileDescriptorTable[i] == NULL) {
id = i;
kernel->fileSystem->fileDescriptorTable[i]
= kernel->fileSystem->Open(name);
if (kernel->fileSystem->fileDescriptorTable[i] == NULL)
return -1;
break;
}
return id;
}
int SysWrite(char *buffer, int size, OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return -1;
return kernel->fileSystem->fileDescriptorTable[id]->Write(buffer, size);
}
int SysRead(char *buffer, int size, OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return -1;
return kernel->fileSystem->fileDescriptorTable[id]->Read(buffer, size);
}
int SysClose(OpenFileId id) {
if (id < 0 || id >= 20 || kernel->fileSystem->fileDescriptorTable[id] == NULL)
return 0;
delete kernel->fileSystem->fileDescriptorTable[id];
kernel->fileSystem->fileDescriptorTable[id] = NULL;
return 1;
}
#endif /* ! __USERPROG_KSYSCALL_H__ */

View File

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

View File

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

View File

@@ -23,19 +23,22 @@
#define SC_Exec 2
#define SC_Join 3
#define SC_Create 4
#define SC_Remove 5
#define SC_Remove 5
#define SC_Open 6
#define SC_Read 7
#define SC_Write 8
#define SC_Seek 9
#define SC_Close 10
#define SC_ThreadFork 11
#define SC_Seek 9
#define SC_Close 10
#define SC_ThreadFork 11
#define SC_ThreadYield 12
#define SC_ExecV 13
#define SC_ExecV 13
#define SC_ThreadExit 14
#define SC_ThreadJoin 15
#define SC_Add 42
#define SC_MSG 100
#define SC_PrintInt 16
#define SC_Add 42
#define SC_MSG 100
#ifndef IN_ASM
@@ -109,7 +112,7 @@ typedef int OpenFileId;
*/
#define SysConsoleInput 0
#define SysConsoleOutput 1
#define SysConsoleOutput 1
/* Create a Nachos file, with name "name" */
/* Note: Create does not open the file. */
@@ -175,7 +178,9 @@ int ThreadJoin(ThreadId id);
/*
* Deletes current thread and returns ExitCode to every waiting lokal thread.
*/
void ThreadExit(int ExitCode);
void ThreadExit(int ExitCode);
void PrintInt(int number);
#endif /* IN_ASM */