Main Page | Alphabetical List | Class List | File List | Class Members | File Members

thread.h

Go to the documentation of this file.
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-1993 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 <setjmp.h> 00043 #include <ucontext.h> 00044 00045 #ifdef USER_PROGRAM 00046 #include "machine.h" 00047 #include "addrspace.h" 00048 #endif 00049 00050 // CPU register state to be saved on context switch. 00051 // The SPARC and MIPS only need 10 registers, but the Snake needs 18. 00052 // For simplicity, this is just the max over all architectures. 00053 #define MachineStateSize 18 00054 00055 00056 // Size of the thread's private execution stack. 00057 // WATCH OUT IF THIS ISN'T BIG ENOUGH!!!!! 00058 #define StackSize (32 * 1024) // in words 00059 00060 00061 // Thread state 00062 enum ThreadStatus { JUST_CREATED, RUNNING, READY, BLOCKED, SLEEPING }; 00063 00064 // external function, dummy routine whose sole job is to call Thread::Print 00065 extern void ThreadPrint(int arg); 00066 00067 // The following class defines a "thread control block" -- which 00068 // represents a single thread of execution. 00069 // 00070 // Every thread has: 00071 // an execution stack for activation records ("stackTop" and "stack") 00072 // space to save CPU registers while not running ("machineState") 00073 // a "status" (running/ready/blocked) 00074 // 00075 // Some threads also belong to a user address space; threads 00076 // that only run in the kernel have a NULL address space. 00077 00078 00079 // The current executing thread may be accessed via a currentThread global 00080 // Thread object pointer. This way the current thread can invoke Suspend 00081 // Yield calls on itself. Given a pointer to another thread the currentThread 00082 // can wakeup another sleeping thread by calling UnSleep (you have to implement 00083 // this function) 00084 00085 class Thread 00086 { 00087 private: 00088 //public: 00089 // NOTE: DO NOT CHANGE the order of these first two members. 00090 // THEY MUST be in this position for SWITCH to work. 00091 int *stackTop; // the current stack pointer 00092 int machineState[MachineStateSize]; // all registers except for stackTop 00093 00094 public: 00095 Thread(char* debugName); // initialize a Thread 00096 ~Thread(); // deallocate a Thread. NOTE -- thread being deleted 00097 // must not be running when delete is called 00098 00099 // basic thread operations 00100 00101 void Fork(VoidFunctionPtr func, int arg); // Make thread run (*func)(arg) 00102 void Yield(); // Relinquish the CPU if any other thread is runnable 00103 void Suspend(); // suspend the thread and relinquish the processor 00104 void Finish(); // The thread is done executing 00105 void Sleep(int sec); // put the current process to sleep for sec seconds 00106 void UnSleep(); // wakeup this thread and place it on the ready queue 00107 00108 void CheckOverflow(); // Check if thread has overflowed its stack 00109 void setStatus(ThreadStatus st) { status = st; } 00110 char* getName() { return (name); } 00111 void Print() { printf("%s, ", name); } 00112 00113 ThreadStatus GetStatus() { return status; } 00114 00115 private: 00116 // some of the private data for this class is listed above 00117 int *stack; // Bottom of the stack NULL if this is the main thread 00118 // (If NULL, don't deallocate stack) 00119 ThreadStatus status; // ready, running or blocked 00120 char* name; 00121 VoidFunctionPtr pfunc; 00122 00123 public: 00124 sigjmp_buf cbuff; 00125 int started; // is this thread just starting out? 00126 char which; 00127 00128 00129 00130 00131 private: 00132 00133 void StackAllocate(VoidFunctionPtr func, int arg); // Allocate a stack for thread. 00134 // Used internally by Fork() 00135 00136 #ifdef USER_PROGRAM 00137 // A thread running a user program actually has *two* sets of CPU registers -- 00138 // one for its state while executing user code, one for its state 00139 // while executing kernel code. 00140 00141 int userRegisters[NumTotalRegs]; // user-level CPU register state 00142 00143 public: 00144 void SaveUserState(); // save user-level register state 00145 void RestoreUserState(); // restore user-level register state 00146 00147 00148 AddrSpace *space; // User code this thread is running. 00149 #endif 00150 }; 00151 00152 // Magical machine-dependent routines, defined in switch.s 00153 00154 extern "C" { 00155 // First frame on thread execution stack; 00156 // enable interrupts 00157 // call "func" 00158 // (when func returns, if ever) call ThreadFinish() 00159 void ThreadRoot(); 00160 00161 // Stop running oldThread and start running newThread 00162 void SWITCH(Thread *oldThread, Thread *newThread); 00163 } 00164 00165 #endif // THREAD_H

Generated on Thu Sep 16 12:33:46 2004 for NachOS by doxygen 1.3.8