00001 // thread.h 00002 // Data structures for managing threads. A thread represents 00003 // sequential execution of code within a program. 00004 // So the state of a thread includes the program counter, 00005 // the processor registers, and the execution stack. 00006 // 00007 // Note that because we allocate a fixed size stack for each 00008 // thread, it is possible to overflow the stack -- for instance, 00009 // by recursing to too deep a level. The most common reason 00010 // for this occuring is allocating large data structures 00011 // on the stack. For instance, this will cause problems: 00012 // 00013 // void foo() { int buf[1000]; ...} 00014 // 00015 // Instead, you should allocate all data structures dynamically: 00016 // 00017 // void foo() { int *buf = new int[1000]; ...} 00018 // 00019 // 00020 // Bad things happen if you overflow the stack, and in the worst 00021 // case, the problem may not be caught explicitly. Instead, 00022 // the only symptom may be bizarre segmentation faults. (Of course, 00023 // other problems can cause seg faults, so that isn't a sure sign 00024 // that your thread stacks are too small.) 00025 // 00026 // One thing to try if you find yourself with seg faults is to 00027 // increase the size of thread stack -- ThreadStackSize. 00028 // 00029 // In this interface, forking a thread takes two steps. 00030 // We must first allocate a data structure for it: "t = new Thread". 00031 // Only then can we do the fork: "t->fork(f, arg)". 00032 // 00033 // Copyright (c) 1992-1996 The Regents of the University of California. 00034 // All rights reserved. See copyright.h for copyright notice and limitation 00035 // of liability and disclaimer of warranty provisions. 00036 00037 #ifndef THREAD_H 00038 #define THREAD_H 00039 00040 #include "copyright.h" 00041 #include "utility.h" 00042 #include "sysdep.h" 00043 00044 #include "machine.h" 00045 #include "addrspace.h" 00046 00047 // CPU register state to be saved on context switch. 00048 // The x86 needs to save only a few registers, 00049 // SPARC and MIPS needs to save 10 registers, 00050 // the Snake needs 18, 00051 // and the RS6000 needs to save 75 (!) 00052 // For simplicity, I just take the maximum over all architectures. 00053 00054 #define MachineStateSize 75 00055 00056 00057 // Size of the thread's private execution stack. 00058 // WATCH OUT IF THIS ISN'T BIG ENOUGH!!!!! 00059 const int StackSize = (8 * 1024); // in words 00060 00061 00062 // Thread state 00063 enum ThreadStatus { JUST_CREATED, RUNNING, READY, BLOCKED }; 00064 00065 00066 // The following class defines a "thread control block" -- which 00067 // represents a single thread of execution. 00068 // 00069 // Every thread has: 00070 // an execution stack for activation records ("stackTop" and "stack") 00071 // space to save CPU registers while not running ("machineState") 00072 // a "status" (running/ready/blocked) 00073 // 00074 // Some threads also belong to a user address space; threads 00075 // that only run in the kernel have a NULL address space. 00076 00077 class Thread { 00078 private: 00079 // NOTE: DO NOT CHANGE the order of these first two members. 00080 // THEY MUST be in this position for SWITCH to work. 00081 int *stackTop; // the current stack pointer 00082 void *machineState[MachineStateSize]; // all registers except for stackTop 00083 00084 public: 00085 Thread(char* debugName); // initialize a Thread 00086 ~Thread(); // deallocate a Thread 00087 // NOTE -- thread being deleted 00088 // must not be running when delete 00089 // is called 00090 00091 // basic thread operations 00092 00093 void Fork(VoidFunctionPtr func, void *arg); 00094 // Make thread run (*func)(arg) 00095 void Yield(); // Relinquish the CPU if any 00096 // other thread is runnable 00097 void Sleep(bool finishing); // Put the thread to sleep and 00098 // relinquish the processor 00099 void Begin(); // Startup code for the thread 00100 void Finish(); // The thread is done executing 00101 00102 void CheckOverflow(); // Check if thread stack has overflowed 00103 void setStatus(ThreadStatus st) { status = st; } 00104 char* getName() { return (name); } 00105 void Print() { cout << name; } 00106 void SelfTest(); // test whether thread impl is working 00107 00108 private: 00109 // some of the private data for this class is listed above 00110 00111 int *stack; // Bottom of the stack 00112 // NULL if this is the main thread 00113 // (If NULL, don't deallocate stack) 00114 ThreadStatus status; // ready, running or blocked 00115 char* name; 00116 00117 void StackAllocate(VoidFunctionPtr func, void *arg); 00118 // Allocate a stack for thread. 00119 // Used internally by Fork() 00120 00121 // A thread running a user program actually has *two* sets of CPU registers -- 00122 // one for its state while executing user code, one for its state 00123 // while executing kernel code. 00124 00125 int userRegisters[NumTotalRegs]; // user-level CPU register state 00126 00127 public: 00128 void SaveUserState(); // save user-level register state 00129 void RestoreUserState(); // restore user-level register state 00130 00131 AddrSpace *space; // User code this thread is running. 00132 }; 00133 00134 // external function, dummy routine whose sole job is to call Thread::Print 00135 extern void ThreadPrint(Thread *thread); 00136 00137 // Magical machine-dependent routines, defined in switch.s 00138 00139 extern "C" { 00140 // First frame on thread execution stack; 00141 // call ThreadBegin 00142 // call "func" 00143 // (when func returns, if ever) call ThreadFinish() 00144 void ThreadRoot(); 00145 00146 // Stop running oldThread and start running newThread 00147 void SWITCH(Thread *oldThread, Thread *newThread); 00148 } 00149 00150 #endif // THREAD_H