00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __thread_h
00009 #define __thread_h
00010
00011 #include <system/config.h>
00012 #include <utility/queue.h>
00013 #include <cpu.h>
00014 #include <mmu.h>
00015 #include <scheduler.h>
00016 #include "ep_cvec.h"
00017
00018 __BEGIN_SYS
00019
00020 const unsigned int NULL = 0;
00021
00026 class Thread {
00027 private:
00028
00029 static const Type_Id TYPE = Type<Thread>::TYPE;
00030
00031 typedef Queue<Thread> Queue;
00032
00033 static const unsigned int STACK_SIZE =
00034 __SYS(Traits)<Machine>::APPLICATION_STACK_SIZE;
00035
00036 typedef CPU::Log_Addr Log_Addr;
00037 typedef CPU::Context Context;
00038
00039 public:
00040 friend class Scheduler;
00041 typedef short State;
00042
00043 typedef short Priority;
00044 enum {
00045 HIGH = 1,
00046 NORMAL = 15,
00047 LOW = 63,
00048 IDLE = 127
00049 };
00050
00051 enum ThreadState {
00052 RUNNING,
00053 READY,
00054 SUSPENDED,
00055 FINISHING,
00056 DESTROYED
00057 };
00058
00059 enum ThreadType {
00060 JOINABLE,
00061 DETACHED
00062 };
00063
00070 Thread(int (* entry)(),
00071 const State & state = READY,
00072 const Priority & priority = NORMAL,
00073 unsigned int stack_size = STACK_SIZE)
00074 : _stack(Scheduler::getInstance().getThreadStack(STACK_SIZE)),
00075 _context(new (_stack + stack_size
00076 - sizeof(int) - sizeof(Context))
00077 Context(entry)),
00078 _state(state),
00079 _priority(priority),
00080 _link(this),
00081 _waitingThread(NULL)
00082 {
00083 header(entry, stack_size);
00084 Log_Addr sp = _stack + stack_size;
00085 sp -= sizeof(int); *static_cast<unsigned int *>(sp) =
00086 reinterpret_cast<unsigned int>(&exit);
00087 body();
00088 }
00089
00090 template<class T1>
00091 Thread(int (* entry)(T1 a1), T1 a1,
00092 const State & state = READY,
00093 const Priority & priority = NORMAL,
00094 unsigned int stack_size = STACK_SIZE)
00095 : _stack(Scheduler::getInstance().getThreadStack(STACK_SIZE)),
00096 _context(new (_stack + stack_size - sizeof(T1)
00097 - sizeof(int) - sizeof(Context))
00098 Context(entry)),
00099 _state(state),
00100 _priority(priority),
00101 _link(this),
00102 _waitingThread(NULL)
00103 {
00104 header(entry, stack_size);
00105 Log_Addr sp = _stack + stack_size;
00106 sp -= sizeof(T1); *static_cast<T1 *>(sp) = a1;
00107 sp -= sizeof(int); *static_cast<unsigned int *>(sp) =
00108 reinterpret_cast<unsigned int>(&exit);
00109 body();
00110 }
00111
00112 template<class T1, class T2>
00113 Thread(int (* entry)(T1 a1, T2 a2), T1 a1, T2 a2,
00114 const State & state = READY,
00115 const Priority & priority = NORMAL,
00116 unsigned int stack_size = STACK_SIZE)
00117 : _stack(Scheduler::getInstance().getThreadStack(STACK_SIZE)),
00118 _context(new (_stack + stack_size - sizeof(T2) - sizeof(T1)
00119 - sizeof(int) - sizeof(Context))
00120 Context(entry)),
00121 _state(state),
00122 _priority(priority),
00123 _link(this),
00124 _waitingThread(NULL)
00125 {
00126 header(entry, stack_size);
00127 Log_Addr sp = _stack + stack_size;
00128 sp -= sizeof(T2); *static_cast<T2 *>(sp) = a2;
00129 sp -= sizeof(T1); *static_cast<T1 *>(sp) = a1;
00130 sp -= sizeof(int); *static_cast<unsigned int *>(sp) =
00131 reinterpret_cast<unsigned int>(&exit);
00132 body();
00133 }
00134
00135 template<class T1, class T2, class T3>
00136 Thread(int (* entry)(T1 a1, T2 a2, T3 a3), T1 a1, T2 a2, T3 a3,
00137 const State & state = READY,
00138 const Priority & priority = NORMAL,
00139 unsigned int stack_size = STACK_SIZE)
00140 : _stack(Scheduler::getInstance().getThreadStack(STACK_SIZE)),
00141 _context(new (_stack + stack_size - sizeof(T3) - sizeof(T2)
00142 - sizeof(T1) - sizeof(int) - sizeof(Context))
00143 Context(entry)),
00144 _state(state),
00145 _priority(priority),
00146 _link(this),
00147 _waitingThread(NULL)
00148 {
00149 header(entry, stack_size);
00150 Log_Addr sp = _stack + stack_size;
00151 sp -= sizeof(T3); *static_cast<T3 *>(sp) = a3;
00152 sp -= sizeof(T2); *static_cast<T2 *>(sp) = a2;
00153 sp -= sizeof(T1); *static_cast<T1 *>(sp) = a1;
00154 sp -= sizeof(int); *static_cast<unsigned int *>(sp) =
00155 reinterpret_cast<unsigned int>(&implicit_exit);
00156 body();
00157 }
00158
00159 ~Thread();
00160
00161 volatile const State & state() const { return _state; }
00162 volatile const Priority & priority() const { return _priority; }
00163 void priority(const Priority & priority);
00164
00165 int join();
00166
00167
00168 inline void pass() {
00169 Scheduler::getInstance().pass(this);
00170 }
00171
00172 inline void suspend() {
00173 Scheduler::getInstance().suspend(this);
00174 }
00175
00176 inline void resume() {
00177 Scheduler::getInstance().resume(this);
00178 }
00179
00180 inline static void yield() {
00181 Scheduler::getInstance().yield();
00182 }
00183
00184 static void exit(int status = 0) {
00185 Scheduler::getInstance().exit(status);
00186 }
00187
00188 inline static Thread* volatile running() { return &Scheduler::getInstance().getRunning(); }
00189
00190 inline void addSemaphore(Semaphore *semaphore) { _semaphores.pushBack(semaphore); }
00191
00192 inline void removeSemaphore(Semaphore *semaphore) { _semaphores.remove(semaphore); }
00193
00194 static int init(System_Info * si);
00195
00196 static void idle();
00197 private:
00198 void header(Log_Addr entry, unsigned int stack_size);
00199 void body();
00200 void releaseSemaphores();
00201 static void implicit_exit() { exit(CPU::fr()); }
00202
00203 Log_Addr _stack;
00204 Context * volatile _context;
00205 volatile State _state;
00206 volatile Priority _priority;
00207 Queue::Element _link;
00208
00212 CircularVector<Semaphore *> _semaphores;
00213 Thread* _waitingThread;
00214
00215 };
00216
00217 __END_SYS
00218
00219 #endif