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