📄 task.hh
字号:
// -*- c-basic-offset: 4; related-file-name: "../../lib/task.cc" -*-#ifndef CLICK_TASK_HH#define CLICK_TASK_HH#include <click/element.hh>#include <click/sync.hh>#if __MTCLICK__# include <click/atomic.hh># include <click/ewma.hh>#endifCLICK_DECLS#ifdef CLICK_BSDMODULE# include <machine/cpu.h># include <assert.h> /* MARKO XXX */#endif#if CLICK_BSDMODULE && !BSD_NETISRSCHED# define SPLCHECK \ int s = splimp(); \ if (s == 0) \ panic("not spl'ed: %d\n", s); \ splx(s);#else# define SPLCHECK#endif#define PASS_GT(a, b) ((int)(a - b) > 0)typedef bool (*TaskHook)(Task *, void *);class RouterThread;class TaskList;class Master;class Task { public:#ifdef HAVE_STRIDE_SCHED enum { STRIDE1 = 1U<<16, MAX_STRIDE = 1U<<31 }; enum { MAX_TICKETS = 1<<15, DEFAULT_TICKETS = 1<<10 };#endif#ifdef HAVE_ADAPTIVE_SCHEDULER enum { MAX_UTILIZATION = 1000 };#endif inline Task(TaskHook, void *); inline Task(Element *); // call element->run_task() ~Task(); bool initialized() const { return _router != 0; }#if HAVE_TASK_HEAP bool scheduled() const { return _schedpos >= 0; }#else bool scheduled() const { return _prev != 0; }#endif TaskHook hook() const { return _hook; } void *thunk() const { return _thunk; } inline Element *element() const;#if !HAVE_TASK_HEAP Task *scheduled_next() const { return _next; } Task *scheduled_prev() const { return _prev; }#endif RouterThread *scheduled_list() const { return _thread; } Master *master() const; #ifdef HAVE_STRIDE_SCHED int tickets() const { return _tickets; } void set_tickets(int); void adj_tickets(int);#endif void initialize(Router *, bool scheduled); void initialize(Element *, bool scheduled); void cleanup(); void uninitialize() { cleanup(); } // deprecated void unschedule(); inline void reschedule(); inline void fast_unschedule();#ifdef HAVE_TASK_HEAP void fast_reschedule();#else inline void fast_reschedule();#endif void strong_unschedule(); void strong_reschedule(); int thread_preference() const { return _thread_preference; } void change_thread(int); inline void call_hook();#ifdef HAVE_ADAPTIVE_SCHEDULER unsigned runs() const { return _runs; } unsigned work_done() const { return _work_done; } inline unsigned utilization() const; void clear_runs() { _runs = _work_done = 0; }#endif#if __MTCLICK__ inline int cycles() const; inline unsigned cycle_runs() const { return _cycle_runs; } inline void update_cycles(unsigned c);#endif private: /* if gcc keeps this ordering, we may get some cache locality on a 16 or 32 * byte cache line: the first three fields are used in list traversal */#ifdef HAVE_TASK_HEAP int _schedpos;#else Task* _prev; Task* _next;#endif #ifdef HAVE_STRIDE_SCHED unsigned _pass; unsigned _stride; int _tickets;#endif TaskHook _hook; void* _thunk; #ifdef HAVE_ADAPTIVE_SCHEDULER unsigned _runs; unsigned _work_done;#endif#if __MTCLICK__ DirectEWMA _cycles; unsigned _cycle_runs;#endif RouterThread* _thread; int _thread_preference; Router* _router; enum { RESCHEDULE = 1, CHANGE_THREAD = 2 }; unsigned _pending; Task* _pending_next; Task(const Task&); Task& operator=(const Task&); void add_pending(int); void process_pending(RouterThread*); inline void fast_schedule(); void true_reschedule(); inline void lock_tasks(); inline bool attempt_lock_tasks(); void make_list(); static bool error_hook(Task*, void*); friend class RouterThread; friend class Master; };// need RouterThread's definition for inline functionsCLICK_ENDDECLS#include <click/routerthread.hh>CLICK_DECLSinlineTask::Task(TaskHook hook, void* thunk)#ifdef HAVE_TASK_HEAP : _schedpos(-1),#else : _prev(0), _next(0),#endif#ifdef HAVE_STRIDE_SCHED _pass(0), _stride(0), _tickets(-1),#endif _hook(hook), _thunk(thunk),#ifdef HAVE_ADAPTIVE_SCHEDULER _runs(0), _work_done(0),#endif#if __MTCLICK__ _cycle_runs(0),#endif _thread(0), _thread_preference(-1), _router(0), _pending(0), _pending_next(0){}inlineTask::Task(Element* e)#ifdef HAVE_TASK_HEAP : _schedpos(-1),#else : _prev(0), _next(0),#endif#ifdef HAVE_STRIDE_SCHED _pass(0), _stride(0), _tickets(-1),#endif _hook(0), _thunk(e),#ifdef HAVE_ADAPTIVE_SCHEDULER _runs(0), _work_done(0),#endif#if __MTCLICK__ _cycle_runs(0),#endif _thread(0), _thread_preference(-1), _router(0), _pending(0), _pending_next(0){}inline Element*Task::element() const{ return _hook ? 0 : reinterpret_cast<Element*>(_thunk); }inline voidTask::fast_unschedule(){#if CLICK_LINUXMODULE assert(!in_interrupt());#endif#if CLICK_BSDMODULE // assert(!intr_nesting_level); SPLCHECK#endif if (scheduled()) {#ifdef HAVE_TASK_HEAP Task* back = _thread->_task_heap.back(); _thread->_task_heap.pop_back(); if (_thread->_task_heap.size() > 0) _thread->task_reheapify_from(_schedpos, back); _schedpos = -1;#else _next->_prev = _prev; _prev->_next = _next; _next = _prev = 0;#endif }}#ifdef HAVE_STRIDE_SCHEDinline void Task::set_tickets(int n){ if (n > MAX_TICKETS) n = MAX_TICKETS; else if (n < 1) n = 1; _tickets = n; _stride = STRIDE1 / n; assert(_stride < MAX_STRIDE);}inline void Task::adj_tickets(int delta){ set_tickets(_tickets + delta);}#ifndef HAVE_TASK_HEAPinline voidTask::fast_reschedule(){ // should not be scheduled at this point assert(_thread);#if CLICK_LINUXMODULE // tasks never run at interrupt time in Linux assert(!in_interrupt());#endif#if CLICK_BSDMODULE // assert(!intr_nesting_level); it happens all the time from fromdevice! SPLCHECK#endif if (!scheduled()) { // increase pass _pass += _stride;#if 0 // look for 'n' immediately before where we should be scheduled Task* n = _thread->_prev; while (n != _thread && PASS_GT(n->_pass, _pass)) n = n->_prev; // schedule after 'n' _next = n->_next; _prev = n; n->_next = this; _next->_prev = this;#else // look for 'n' immediately after where we should be scheduled Task* n = _thread->_next;#ifdef CLICK_BSDMODULE /* XXX MARKO a race occured here when not spl'ed */ while (n->_next != NULL && n != _thread && !PASS_GT(n->_pass, _pass))#else while (n != _thread && !PASS_GT(n->_pass, _pass))#endif n = n->_next; // schedule before 'n' _prev = n->_prev; _next = n; _prev->_next = this; n->_prev = this;#endif }}#endifinline voidTask::fast_schedule(){ SPLCHECK assert(_tickets >= 1);#if HAVE_TASK_HEAP _pass = (_thread->empty() ? 0 : _thread->_task_heap[0]->_pass);#else _pass = _thread->_next->_pass;#endif fast_reschedule();}#else /* !HAVE_STRIDE_SCHED */inline voidTask::fast_reschedule(){ assert(_thread);#if CLICK_LINUXMODULE // tasks never run at interrupt time assert(!in_interrupt());#endif#if CLICK_BSDMODULE // assert(!intr_nesting_level); SPLCHECK#endif if (!scheduled()) { _prev = _thread->_prev; _next = _thread; _thread->_prev = this; _thread->_next = this; }}inline voidTask::fast_schedule(){ fast_reschedule();}#endif /* HAVE_STRIDE_SCHED */inline voidTask::reschedule(){ SPLCHECK assert(_thread); if (!scheduled()) true_reschedule();}inline voidTask::call_hook(){#if __MTCLICK__ _cycle_runs++;#endif#ifdef HAVE_ADAPTIVE_SCHEDULER _runs++; if (!_hook) _work_done += ((Element*)_thunk)->run_task(); else _work_done += _hook(this, _thunk);#else if (!_hook) (void) ((Element*)_thunk)->run_task(); else (void) _hook(this, _thunk);#endif}#ifdef HAVE_ADAPTIVE_SCHEDULERinline unsignedTask::utilization() const{ return (_runs ? (MAX_UTILIZATION * _work_done) / _runs : 0);}#endif#if __MTCLICK__inline intTask::cycles() const{ return _cycles.average() >> _cycles.scale;}inline voidTask::update_cycles(unsigned c) { _cycles.update_with(c); _cycle_runs = 0;}#endifCLICK_ENDDECLS#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -