Ytshih/hw2
This commit is contained in:
@@ -35,17 +35,17 @@ const int STACK_FENCEPOST = 0xdedbeef;
|
||||
|
||||
Thread::Thread(char* threadName, int threadID)
|
||||
{
|
||||
ID = threadID;
|
||||
name = threadName;
|
||||
stackTop = NULL;
|
||||
stack = NULL;
|
||||
status = JUST_CREATED;
|
||||
for (int i = 0; i < MachineStateSize; i++) {
|
||||
machineState[i] = NULL; // not strictly necessary, since
|
||||
// new thread ignores contents
|
||||
// of machine registers
|
||||
}
|
||||
space = NULL;
|
||||
ID = threadID;
|
||||
name = threadName;
|
||||
stackTop = NULL;
|
||||
stack = NULL;
|
||||
status = JUST_CREATED;
|
||||
for (int i = 0; i < MachineStateSize; i++) {
|
||||
machineState[i] = NULL; // not strictly necessary, since
|
||||
// new thread ignores contents
|
||||
// of machine registers
|
||||
}
|
||||
space = NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -62,10 +62,10 @@ Thread::Thread(char* threadName, int threadID)
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
DEBUG(dbgThread, "Deleting thread: " << name);
|
||||
ASSERT(this != kernel->currentThread);
|
||||
if (stack != NULL)
|
||||
DeallocBoundedArray((char *) stack, StackSize * sizeof(int));
|
||||
DEBUG(dbgThread, "Deleting thread: " << name);
|
||||
ASSERT(this != kernel->currentThread);
|
||||
if (stack != NULL)
|
||||
DeallocBoundedArray((char *) stack, StackSize * sizeof(int));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -91,17 +91,17 @@ Thread::~Thread()
|
||||
void
|
||||
Thread::Fork(VoidFunctionPtr func, void *arg)
|
||||
{
|
||||
Interrupt *interrupt = kernel->interrupt;
|
||||
Scheduler *scheduler = kernel->scheduler;
|
||||
IntStatus oldLevel;
|
||||
|
||||
DEBUG(dbgThread, "Forking thread: " << name << " f(a): " << (int) func << " " << arg);
|
||||
StackAllocate(func, arg);
|
||||
Interrupt *interrupt = kernel->interrupt;
|
||||
Scheduler *scheduler = kernel->scheduler;
|
||||
IntStatus oldLevel;
|
||||
|
||||
oldLevel = interrupt->SetLevel(IntOff);
|
||||
scheduler->ReadyToRun(this); // ReadyToRun assumes that interrupts
|
||||
// are disabled!
|
||||
(void) interrupt->SetLevel(oldLevel);
|
||||
DEBUG(dbgThread, "Forking thread: " << name << " f(a): " << (int) func << " " << arg);
|
||||
StackAllocate(func, arg);
|
||||
|
||||
oldLevel = interrupt->SetLevel(IntOff);
|
||||
scheduler->ReadyToRun(this); // ReadyToRun assumes that interrupts
|
||||
// are disabled!
|
||||
(void) interrupt->SetLevel(oldLevel);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -122,13 +122,13 @@ Thread::Fork(VoidFunctionPtr func, void *arg)
|
||||
void
|
||||
Thread::CheckOverflow()
|
||||
{
|
||||
if (stack != NULL) {
|
||||
if (stack != NULL) {
|
||||
#ifdef HPUX // Stacks grow upward on the Snakes
|
||||
ASSERT(stack[StackSize - 1] == STACK_FENCEPOST);
|
||||
ASSERT(stack[StackSize - 1] == STACK_FENCEPOST);
|
||||
#else
|
||||
ASSERT(*stack == STACK_FENCEPOST);
|
||||
ASSERT(*stack == STACK_FENCEPOST);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -170,12 +170,12 @@ Thread::Begin ()
|
||||
void
|
||||
Thread::Finish ()
|
||||
{
|
||||
(void) kernel->interrupt->SetLevel(IntOff);
|
||||
ASSERT(this == kernel->currentThread);
|
||||
|
||||
DEBUG(dbgThread, "Finishing thread: " << name);
|
||||
Sleep(TRUE); // invokes SWITCH
|
||||
// not reached
|
||||
(void) kernel->interrupt->SetLevel(IntOff);
|
||||
ASSERT(this == kernel->currentThread);
|
||||
|
||||
DEBUG(dbgThread, "Finishing thread: " << name);
|
||||
Sleep(TRUE); // invokes SWITCH
|
||||
// not reached
|
||||
}
|
||||
|
||||
|
||||
@@ -200,19 +200,19 @@ Thread::Finish ()
|
||||
void
|
||||
Thread::Yield ()
|
||||
{
|
||||
Thread *nextThread;
|
||||
IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);
|
||||
|
||||
ASSERT(this == kernel->currentThread);
|
||||
|
||||
DEBUG(dbgThread, "Yielding thread: " << name);
|
||||
|
||||
nextThread = kernel->scheduler->FindNextToRun();
|
||||
if (nextThread != NULL) {
|
||||
kernel->scheduler->ReadyToRun(this);
|
||||
kernel->scheduler->Run(nextThread, FALSE);
|
||||
}
|
||||
(void) kernel->interrupt->SetLevel(oldLevel);
|
||||
Thread *nextThread;
|
||||
IntStatus oldLevel = kernel->interrupt->SetLevel(IntOff);
|
||||
|
||||
ASSERT(this == kernel->currentThread);
|
||||
|
||||
DEBUG(dbgThread, "Yielding thread: " << name);
|
||||
|
||||
nextThread = kernel->scheduler->FindNextToRun();
|
||||
if (nextThread != NULL) {
|
||||
kernel->scheduler->ReadyToRun(this);
|
||||
kernel->scheduler->Run(nextThread, FALSE);
|
||||
}
|
||||
(void) kernel->interrupt->SetLevel(oldLevel);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -238,20 +238,20 @@ Thread::Yield ()
|
||||
void
|
||||
Thread::Sleep (bool finishing)
|
||||
{
|
||||
Thread *nextThread;
|
||||
|
||||
ASSERT(this == kernel->currentThread);
|
||||
ASSERT(kernel->interrupt->getLevel() == IntOff);
|
||||
|
||||
DEBUG(dbgThread, "Sleeping thread: " << name);
|
||||
Thread *nextThread;
|
||||
|
||||
status = BLOCKED;
|
||||
//cout << "debug Thread::Sleep " << name << "wait for Idle\n";
|
||||
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL) {
|
||||
kernel->interrupt->Idle(); // no one to run, wait for an interrupt
|
||||
}
|
||||
// returns when it's time for us to run
|
||||
kernel->scheduler->Run(nextThread, finishing);
|
||||
ASSERT(this == kernel->currentThread);
|
||||
ASSERT(kernel->interrupt->getLevel() == IntOff);
|
||||
|
||||
DEBUG(dbgThread, "Sleeping thread: " << name);
|
||||
|
||||
status = BLOCKED;
|
||||
//cout << "debug Thread::Sleep " << name << "wait for Idle\n";
|
||||
while ((nextThread = kernel->scheduler->FindNextToRun()) == NULL) {
|
||||
kernel->interrupt->Idle(); // no one to run, wait for an interrupt
|
||||
}
|
||||
// returns when it's time for us to run
|
||||
kernel->scheduler->Run(nextThread, finishing);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -262,7 +262,7 @@ Thread::Sleep (bool finishing)
|
||||
// member function.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static void ThreadFinish() { kernel->currentThread->Finish(); }
|
||||
static void ThreadFinish() { kernel->currentThread->Finish(); }
|
||||
static void ThreadBegin() { kernel->currentThread->Begin(); }
|
||||
void ThreadPrint(Thread *t) { t->Print(); }
|
||||
|
||||
@@ -277,16 +277,16 @@ void ThreadPrint(Thread *t) { t->Print(); }
|
||||
static void *
|
||||
PLabelToAddr(void *plabel)
|
||||
{
|
||||
int funcPtr = (int) plabel;
|
||||
int funcPtr = (int) plabel;
|
||||
|
||||
if (funcPtr & 0x02) {
|
||||
// L-Field is set. This is a PLT pointer
|
||||
funcPtr -= 2; // Get rid of the L bit
|
||||
return (*(void **)funcPtr);
|
||||
} else {
|
||||
// L-field not set.
|
||||
return plabel;
|
||||
}
|
||||
if (funcPtr & 0x02) {
|
||||
// L-Field is set. This is a PLT pointer
|
||||
funcPtr -= 2; // Get rid of the L bit
|
||||
return (*(void **)funcPtr);
|
||||
} else {
|
||||
// L-field not set.
|
||||
return plabel;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -305,59 +305,59 @@ PLabelToAddr(void *plabel)
|
||||
void
|
||||
Thread::StackAllocate (VoidFunctionPtr func, void *arg)
|
||||
{
|
||||
stack = (int *) AllocBoundedArray(StackSize * sizeof(int));
|
||||
stack = (int *) AllocBoundedArray(StackSize * sizeof(int));
|
||||
|
||||
#ifdef PARISC
|
||||
// HP stack works from low addresses to high addresses
|
||||
// everyone else works the other way: from high addresses to low addresses
|
||||
stackTop = stack + 16; // HP requires 64-byte frame marker
|
||||
stack[StackSize - 1] = STACK_FENCEPOST;
|
||||
// HP stack works from low addresses to high addresses
|
||||
// everyone else works the other way: from high addresses to low addresses
|
||||
stackTop = stack + 16; // HP requires 64-byte frame marker
|
||||
stack[StackSize - 1] = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
#ifdef SPARC
|
||||
stackTop = stack + StackSize - 96; // SPARC stack must contains at
|
||||
// least 1 activation record
|
||||
// to start with.
|
||||
*stack = STACK_FENCEPOST;
|
||||
stackTop = stack + StackSize - 96; // SPARC stack must contains at
|
||||
// least 1 activation record
|
||||
// to start with.
|
||||
*stack = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
#ifdef PowerPC // RS6000
|
||||
stackTop = stack + StackSize - 16; // RS6000 requires 64-byte frame marker
|
||||
*stack = STACK_FENCEPOST;
|
||||
stackTop = stack + StackSize - 16; // RS6000 requires 64-byte frame marker
|
||||
*stack = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
#ifdef DECMIPS
|
||||
stackTop = stack + StackSize - 4; // -4 to be on the safe side!
|
||||
*stack = STACK_FENCEPOST;
|
||||
stackTop = stack + StackSize - 4; // -4 to be on the safe side!
|
||||
*stack = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
#ifdef ALPHA
|
||||
stackTop = stack + StackSize - 8; // -8 to be on the safe side!
|
||||
*stack = STACK_FENCEPOST;
|
||||
stackTop = stack + StackSize - 8; // -8 to be on the safe side!
|
||||
*stack = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef x86
|
||||
// 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
|
||||
// used in SWITCH() must be the starting address of ThreadRoot.
|
||||
stackTop = stack + StackSize - 4; // -4 to be on the safe side!
|
||||
*(--stackTop) = (int) ThreadRoot;
|
||||
*stack = STACK_FENCEPOST;
|
||||
// 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
|
||||
// used in SWITCH() must be the starting address of ThreadRoot.
|
||||
stackTop = stack + StackSize - 4; // -4 to be on the safe side!
|
||||
*(--stackTop) = (int) ThreadRoot;
|
||||
*stack = STACK_FENCEPOST;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PARISC
|
||||
machineState[PCState] = PLabelToAddr(ThreadRoot);
|
||||
machineState[StartupPCState] = PLabelToAddr(ThreadBegin);
|
||||
machineState[InitialPCState] = PLabelToAddr(func);
|
||||
machineState[InitialArgState] = arg;
|
||||
machineState[WhenDonePCState] = PLabelToAddr(ThreadFinish);
|
||||
machineState[PCState] = PLabelToAddr(ThreadRoot);
|
||||
machineState[StartupPCState] = PLabelToAddr(ThreadBegin);
|
||||
machineState[InitialPCState] = PLabelToAddr(func);
|
||||
machineState[InitialArgState] = arg;
|
||||
machineState[WhenDonePCState] = PLabelToAddr(ThreadFinish);
|
||||
#else
|
||||
machineState[PCState] = (void*)ThreadRoot;
|
||||
machineState[StartupPCState] = (void*)ThreadBegin;
|
||||
machineState[InitialPCState] = (void*)func;
|
||||
machineState[InitialArgState] = (void*)arg;
|
||||
machineState[WhenDonePCState] = (void*)ThreadFinish;
|
||||
machineState[PCState] = (void*)ThreadRoot;
|
||||
machineState[StartupPCState] = (void*)ThreadBegin;
|
||||
machineState[InitialPCState] = (void*)func;
|
||||
machineState[InitialArgState] = (void*)arg;
|
||||
machineState[WhenDonePCState] = (void*)ThreadFinish;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -391,8 +391,8 @@ Thread::SaveUserState()
|
||||
void
|
||||
Thread::RestoreUserState()
|
||||
{
|
||||
for (int i = 0; i < NumTotalRegs; i++)
|
||||
kernel->machine->WriteRegister(i, userRegisters[i]);
|
||||
for (int i = 0; i < NumTotalRegs; i++)
|
||||
kernel->machine->WriteRegister(i, userRegisters[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user