// EPOS-- Thread Abstraction Declarations #ifndef __thread_h #define __thread_h #include #include #include #include #include __BEGIN_SYS class Thread { friend class Scheduler; protected: template class Priority_Updater{ public: static void update(Thread * prev, Thread * next){} }; template class Priority_Updater{ public: static void update(Thread * prev, Thread * next){ ((Scheduling_Criteria::Priority)(prev->link()->rank())).update(prev->computation_start()); next->reset_computation_start(); ((Scheduling_Criteria::Priority)(next->link()->rank())).reset(); } }; static const bool active_scheduler = Traits::Criterion::timed; static const bool preemptive = Traits::Criterion::preemptive; static const bool smp = Traits::smp; static const unsigned int QUANTUM = Traits::QUANTUM; static const unsigned int STACK_SIZE = Traits::APPLICATION_STACK_SIZE; typedef CPU::Log_Addr Log_Addr; typedef CPU::Context Context; public: // Thread State enum State { BEGINNING, READY, RUNNING, SUSPENDED, WAITING, FINISHING }; // Thread Priority typedef Scheduling_Criteria::Priority Priority; // Thread Scheduling Criterion typedef Traits::Criterion Criterion; enum { NORMAL = Criterion::NORMAL, MAIN = Criterion::MAIN, IDLE = Criterion::IDLE }; // Thread Queue typedef Ordered_Queue::Element> Queue; public: Thread(int (* entry)(), const State & state = READY, const Criterion & criterion = NORMAL, unsigned int stack_size = STACK_SIZE) : _state(state), _waiting(0), _joining(0), _link(this, criterion) { lock(); _stack = kmalloc(stack_size); _context = CPU::init_stack(_stack, stack_size, &implicit_exit, entry); common_constructor(entry, stack_size); } template Thread(int (* entry)(T1 a1), T1 a1, const State & state = READY, const Criterion & criterion = NORMAL, unsigned int stack_size = STACK_SIZE) : _state(state), _waiting(0), _joining(0), _link(this, criterion) { lock(); _stack = kmalloc(stack_size); _context = CPU::init_stack(_stack, stack_size, &implicit_exit, entry, a1); common_constructor(entry, stack_size); } template Thread(int (* entry)(T1 a1, T2 a2), T1 a1, T2 a2, const State & state = READY, const Criterion & criterion = NORMAL, unsigned int stack_size = STACK_SIZE) : _state(state), _waiting(0), _joining(0), _link(this, criterion) { lock(); _stack = kmalloc(stack_size); _context = CPU::init_stack(_stack, stack_size, &implicit_exit, entry, a1, a2); common_constructor(entry, stack_size); } template Thread(int (* entry)(T1 a1, T2 a2, T3 a3), T1 a1, T2 a2, T3 a3, const State & state = READY, const Criterion & criterion = NORMAL, unsigned int stack_size = STACK_SIZE) : _state(state), _waiting(0), _joining(0), _link(this, criterion) { lock(); _stack = kmalloc(stack_size); _context = CPU::init_stack(_stack, stack_size, &implicit_exit, entry, a1, a2, a3); common_constructor(entry, stack_size); } ~Thread(); const volatile State & state() const { return _state; } const volatile Criterion & criterion() const { return _link.rank(); } Priority priority() const { return int(_link.rank()); } void priority(const Priority & p); int join(); void pass(); void suspend() { suspend(false); } void resume(); static Thread * self() { return running(); } static void yield(); static void sleep(Queue * q); static void wakeup(Queue * q); static void wakeup_all(Queue * q); static void exit(int status = 0); static void init(); protected: void common_constructor(Log_Addr entry, unsigned int stack_size); static Thread * volatile running() { return _scheduler.chosen(); } Queue::Element * link() { return &_link; } static void lock() { CPU::int_disable(); if(smp) _lock.acquire(); } static void unlock() { if(smp) _lock.release(); CPU::int_enable(); } void suspend(bool locked); Timer::Tick computation_start() {return _computation_start;} void reset_computation_start(); static void reschedule(bool preempt = preemptive); static void time_slicer(); static void implicit_exit(); static void dispatch(Thread * prev, Thread * next, bool charge = true) { if(charge) if(active_scheduler) Thread::Priority_Updater::Criterion>::update(prev, next); if(prev != next) { if(prev->_state == RUNNING) prev->_state = READY; next->_state = RUNNING; db(TRC) << "Thread::dispatch(prev=" << prev << ",next=" << next << ")\n"; if(smp) _lock.release(); CPU::switch_context(&prev->_context, next->_context); } else if(smp) _lock.release(); CPU::int_enable(); } static int idle(); protected: Log_Addr _stack; Context * volatile _context; volatile State _state; Queue * _waiting; Thread * volatile _joining; Queue::Element _link; Timer::Tick _computation_start; static Spin _lock; static Scheduler_Timer * _timer; static unsigned int _thread_count; static Scheduler _scheduler; }; // An event handler that triggers a thread (see handler.h) class Thread_Handler : public Handler { public: Thread_Handler(Thread * h) : _handler(h) {} ~Thread_Handler() {} void operator()() { _handler->resume(); } private: Thread * _handler; }; __END_SYS #endif