⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.cc

📁 Nachos 线程
💻 CC
📖 第 1 页 / 共 2 页
字号:
// thread.cc //	Routines to manage threads.  There are four main operations:////	Fork -- create a thread to run a procedure concurrently//		with the caller (this is done in two steps -- first//		allocate the Thread object, then call Fork on it)//	Finish -- called when the forked procedure finishes, to clean up//	Yield -- relinquish control over the CPU to another ready thread//	Sleep -- relinquish control over the CPU, but thread is now blocked.//		In other words, it will not run again, until explicitly //		put back on the ready queue.//// Copyright (c) 1992-1993 The Regents of the University of California.// All rights reserved.  See copyright.h for copyright notice and limitation // of liability and disclaimer of warranty provisions.#include "copyright.h"#include "thread.h"#include "switch.h"#include "synch.h"#include "system.h"#define STACK_FENCEPOST 0xdeadbeef	// this is put at the top of the					// execution stack, for detecting 					// stack overflows//----------------------------------------------------------------------// Thread::Thread// 	Initialize a thread control block, so that we can then call//	Thread::Fork.////	"threadName" is an arbitrary string, useful for debugging.//----------------------------------------------------------------------Thread::Thread(char* threadName, int prior){    name = new char[strlen(threadName)];    strcpy( name, threadName );    if (currentThread == NULL)      priority = NORM_PRIORITY;    else if ( prior == -1 )      priority = currentThread->getPriority();    else priority = prior;    interrupted = false;    joinList = new List<Thread *>();    stackTop = NULL;    stack = NULL;    status = JUST_CREATED;#ifdef USER_PROGRAM    space = NULL;#endif}//----------------------------------------------------------------------// Thread::~Thread// 	De-allocate a thread.//// 	NOTE: the current thread *cannot* delete itself directly,//	since it is still running on the stack that we need to delete.////      NOTE: if this is the main thread, we can't delete the stack//      because we didn't allocate it -- we got it automatically//      as part of starting up Nachos.//----------------------------------------------------------------------Thread::~Thread(){    DEBUG('t', "Deleting thread \"%s\"\n", name);    ASSERT(this != currentThread);    if (stack != NULL)	DeallocBoundedArray((char *) stack, StackSize * sizeof(int));}//----------------------------------------------------------------------// Thread::setPriority// Sets thread priority. Note that this method causes a context switch// if the thread is in the ready queue and the new priority of the thread // is the highest in the ready queue. Note that the thread (whose priority// is being set) need not be in the ready queue. It might just have been// created, might be blocked, suspended etc.//----------------------------------------------------------------------void Thread::setPriority(int prior) {    ASSERT( false );}  //----------------------------------------------------------------------// NEW// Interrupts this thread. //----------------------------------------------------------------------void Thread::Interrupt() {  interrupted = true;}//----------------------------------------------------------------------// NEW// Tests if the current thread has been interrupted. //----------------------------------------------------------------------bool Thread::Interrupted() {  bool result = interrupted;  interrupted = false;  return result;}//----------------------------------------------------------------------// CHANGED// Thread::Fork// 	Invoke (*func)(arg), allowing caller and callee to execute //	concurrently.////	NOTE: although our definition allows only a single integer argument//	to be passed to the procedure, it is possible to pass multiple//	arguments by making them fields of a structure, and passing a pointer//	to the structure as "arg".//// 	Implemented as the following steps://		1. Allocate a stack//		2. Initialize the stack so that a call to SWITCH will//		cause it to run the procedure//		3. Put the thread on the ready queue// 	//	"func" is the procedure to run concurrently.//	"arg" is a single argument to be passed to the procedure.////      NOTE: This method may result in a context switch.  //----------------------------------------------------------------------void Thread::Fork(VoidFunctionPtr func, int arg){    DEBUG('t', "Forking thread \"%s\" with func = 0x%x, arg = %d\n",	  name, (int) func, arg);        StackAllocate(func, arg);    IntStatus oldLevel = interrupt->SetLevel(IntOff);    if ( scheduler->ShouldISwitch(currentThread, this) ) {      if( interrupt->IsInHandler() ) {         scheduler->ReadyToRun(this);         interrupt->YieldOnReturn();      } else       {         scheduler->ReadyToRun(currentThread);         scheduler->Run(this);      }    }    else       scheduler->ReadyToRun(this);    (void) interrupt->SetLevel(oldLevel);}    //------------------------------------------------------------------------//  NEW//  NOTE: Only other threads may do a join on this thread.////------------------------------------------------------------------------voidThread::Join(){    Thread *nextThread;    ASSERT (this != currentThread);    IntStatus oldLevel = interrupt->SetLevel(IntOff);    currentThread->setStatus(BLOCKED);    joinList->Append(currentThread);    while ((nextThread = scheduler->FindNextToRun()) == NULL)      interrupt->Idle();       // No thread to run, wait for an interrupt,                               // the only way to enabled threads to execute    scheduler->Run(nextThread);    (void) interrupt->SetLevel(oldLevel);}//------------------------------------------------------------------------//  Thread::Suspend()//      //------------------------------------------------------------------------void Thread::Suspend() {  IntStatus oldLevel = interrupt->SetLevel(IntOff);    printf("Student's suspend routine called\n");  //  ASSERT(this != currentThread);  DEBUG('t', "Thread \"%s\" suspending thread \"%s\"\n", currentThread->getName(), getName());  // Inform the scheduler which maintains the ready and suspended   // list of threads to suspend the thread.  scheduler->Suspend(this);  (void) interrupt->SetLevel(oldLevel);} //------------------------------------------------------------------------//  NEW//  NOTE: Only other threads may suspend this thread.////------------------------------------------------------------------------void Thread::Resume() {  IntStatus oldLevel = interrupt->SetLevel(IntOff);    ASSERT(this != currentThread);  DEBUG('t', "Thread \"%s\" resuming thread \"%s\"\n", currentThread->getName(), getName());  // Inform the scheduler which maintains the ready and suspended   // list of threads to suspend the thread.  scheduler->Resume(this);  (void) interrupt->SetLevel(oldLevel);  }//----------------------------------------------------------------------// Thread::CheckOverflow// 	Check a thread's stack to see if it has overrun the space//	that has been allocated for it.  If we had a smarter compiler,//	we wouldn't need to worry about this, but we don't.//// 	NOTE: Nachos will not catch all stack overflow conditions.//	In other words, your program may still crash because of an overflow.//// 	If you get bizarre results (such as seg faults where there is no code)// 	then you *may* need to increase the stack size.  You can avoid stack

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -