2#ifndef CLICK_ROUTERTHREAD_HH
3#define CLICK_ROUTERTHREAD_HH
6#include <click/timerset.hh>
8# include <click/cxxprotect.h>
10# include <linux/sched.h>
12# include <click/cxxunprotect.h>
14# include <click/cxxprotect.h>
16# include <sys/systm.h>
18# include <click/cxxunprotect.h>
20# include <click/selectset.hh>
24# include <click/multithread.hh>
34 enum { THREAD_QUIESCENT = -1, THREAD_UNKNOWN = -1000 };
36 inline int thread_id()
const;
38 inline Master *master()
const;
39 inline TimerSet &timer_set() {
return _timers; }
40 inline const TimerSet &timer_set()
const {
return _timers; }
42 inline SelectSet &select_set() {
return _selects; }
43 inline const SelectSet &select_set()
const {
return _selects; }
47 inline bool active()
const;
48 inline Task *task_begin()
const;
49 inline Task *task_next(
Task *task)
const;
50 inline Task *task_end()
const;
53 inline void lock_tasks();
54 inline void unlock_tasks();
56 inline void schedule_block_tasks();
57 inline void block_tasks(
bool scheduled);
58 inline void unblock_tasks();
60 inline bool stop_flag()
const;
62 inline void mark_driver_entry();
65 void kill_router(
Router *router);
67#if HAVE_ADAPTIVE_SCHEDULER
70 unsigned min_cpu_share()
const {
return _min_click_share; }
71 unsigned max_cpu_share()
const {
return _max_click_share; }
72 unsigned cur_cpu_share()
const {
return _cur_click_share; }
73 void set_cpu_share(
unsigned min_share,
unsigned max_share);
80 unsigned long long load_cycles();
81 unsigned long long useful_kcycles();
84#if CLICK_LINUXMODULE || CLICK_BSDMODULE
85 bool greedy()
const {
return _greedy; }
86 void set_greedy(
bool g) { _greedy = g; }
92 inline void run_signals();
95 enum { S_PAUSED, S_BLOCKED, S_TIMERWAIT,
96 S_LOCKSELECT, S_LOCKTASKS,
97 S_RUNTASK, S_RUNTIMER, S_RUNSIGNAL, S_RUNPENDING, S_RUNSELECT,
99 inline void set_thread_state(
int state);
100 inline void set_thread_state_for_blocking(
int delay_type);
101#if CLICK_DEBUG_SCHEDULING
102 int thread_state()
const {
return _thread_state; }
103 static String thread_state_name(
int state);
104 uint32_t driver_epoch()
const {
return _driver_epoch; }
105 uint32_t driver_task_epoch()
const {
return _driver_task_epoch; }
106 Timestamp task_epoch_time(uint32_t epoch)
const;
107# if CLICK_LINUXMODULE
108 struct task_struct *sleeper()
const {
return _linux_task; }
110# if CLICK_DEBUG_SCHEDULING > 1
111 inline Timestamp thread_state_time(
int state)
const;
112 inline uint64_t thread_state_count(
int state)
const;
119 struct task_heap_element {
122 task_heap_element() {
124 task_heap_element(
Task *t_)
125 : pass(t_->_pass), t(t_) {
132 volatile bool _stop_flag;
142#if HAVE_ADAPTIVE_SCHEDULER
143 enum { C_CLICK, C_KERNEL, NCLIENTS };
148 Client() : pass(0), tickets(0) { }
150 Client _clients[NCLIENTS];
151 unsigned _global_pass;
152 unsigned _max_click_share;
153 unsigned _min_click_share;
154 unsigned _cur_click_share;
156 int _adaptive_restride_iter;
161 LoadState() : load(), useful(0),useless(0), all_useful_kcycles(0), last_update(0) {
164 EXPSMOOTH<512,10> load;
167 uint64_t all_useful_kcycles;
168 click_cycles_t last_update;
170 click_cycles_t UPDATE_TIME;
175 Spinlock _task_lock CLICK_ALIGNED(CLICK_CACHE_LINE_SIZE);
181 Task::Pending _pending_head;
182 Task::Pending *_pending_tail;
186 Master *_master CLICK_ALIGNED(CLICK_CACHE_LINE_SIZE);
188 bool _driver_entered;
189#if HAVE_MULTITHREAD && !(CLICK_LINUXMODULE || CLICK_MINIOS)
190 click_processor_t _running_processor;
194 struct task_struct *_linux_task;
197 struct thread *_minios_thread;
200 unsigned _tasks_per_iter;
201 unsigned _iters_per_os;
208 enum { ns_iters_per_time = 1000 };
219#if CLICK_DEBUG_SCHEDULING
221 uint32_t _driver_epoch;
222 uint32_t _driver_task_epoch;
223 enum { TASK_EPOCH_BUFSIZ = 32 };
224 uint32_t _task_epoch_first;
225 Timestamp _task_epoch_time[TASK_EPOCH_BUFSIZ];
226# if CLICK_DEBUG_SCHEDULING > 1
228 uint64_t _thread_state_count[NSTATES];
238 inline void add_pending();
240 inline unsigned pass()
const {
244 return _task_link._next->_pass;
250 void driver_lock_tasks();
251 inline void driver_unlock_tasks() {
252#if ! CLICK_ATOMIC_COMPARE_SWAP
255 uint32_t val = _task_blocker.compare_swap((uint32_t) -1, 0);
257 assert(val == (uint32_t) -1);
261 inline bool run_tasks(
int ntasks);
262 inline void process_pending();
263 inline bool run_os();
264#if HAVE_ADAPTIVE_SCHEDULER
265 void client_set_tickets(
int client,
int tickets);
266 inline void client_update_pass(
int client,
const Timestamp &before);
269 void task_reheapify_from(
int pos,
Task*);
271 static inline bool running_in_interrupt();
272 inline bool current_thread_is_running()
const;
273 inline bool current_thread_is_running_cleanup()
const;
276 friend class IdleTask;
279 friend class SelectSet;
313 click_compiler_fence();
315 return _task_heap.size() != 0 || _pending_head.x;
317 return _task_link._next != &_task_link || _pending_head.x;
348 return (_task_heap.size() ? _task_heap.unchecked_at(0).t : 0);
350 return static_cast<Task *
>(_task_link._next);
367 int p = task->_schedpos + 1;
368 return (p < _task_heap.size() ? _task_heap.unchecked_at(p).t : 0);
370 return static_cast<Task *
>(task->_next);
386 return static_cast<Task *
>(
const_cast<TaskLink *
>(&_task_link));
391RouterThread::running_in_interrupt()
394 return in_interrupt();
401RouterThread::mark_driver_entry()
403 _driver_entered =
true;
407RouterThread::current_thread_is_running()
const
410 return current == _linux_task && !running_in_interrupt();
412 return get_current() == _minios_thread;
413#elif CLICK_USERLEVEL && HAVE_MULTITHREAD && HAVE___THREAD_STORAGE_CLASS
414 return click_current_thread_id == (_id | 0x40000000);
415#elif CLICK_USERLEVEL && HAVE_MULTITHREAD
416 return click_current_processor() == _running_processor;
423RouterThread::current_thread_is_running_cleanup()
const
425 return current_thread_is_running() || (!_driver_entered && _id >= 0);
429RouterThread::schedule_block_tasks()
431 assert(!current_thread_is_running());
432 ++_task_blocker_waiting;
436RouterThread::block_tasks(
bool scheduled)
438 assert(!current_thread_is_running() && !running_in_interrupt());
440 ++_task_blocker_waiting;
442 uint32_t blocker = _task_blocker.value();
443 if ((int32_t) blocker >= 0
444#
if ! CLICK_ATOMIC_COMPARE_SWAP
445 && _task_blocker.compare_and_swap(blocker, blocker + 1))
447 && _task_blocker.compare_swap(blocker, blocker + 1) == blocker)
462 --_task_blocker_waiting;
466RouterThread::unblock_tasks()
468 assert((int32_t) _task_blocker.value() > 0);
473RouterThread::lock_tasks()
475 assert(!running_in_interrupt());
476 if (unlikely(!current_thread_is_running())) {
478 _task_lock.acquire();
483RouterThread::unlock_tasks()
485 assert(!running_in_interrupt());
486 if (unlikely(!current_thread_is_running())) {
487 _task_lock.release();
496 struct task_struct *task = _linux_task;
498 wake_up_process(task);
501 if (!current_thread_is_running())
502 _selects.wake_immediate();
503#elif CLICK_BSDMODULE && !BSD_NETISRSCHED
505 wakeup_one(&_sleep_ident);
510RouterThread::add_pending()
516RouterThread::stop_flag()
const
522RouterThread::set_thread_state(
int state)
525#if CLICK_DEBUG_SCHEDULING
526 assert(state >= 0 && state < NSTATES);
527# if CLICK_DEBUG_SCHEDULING > 1
529 if (_thread_state_timestamp)
530 _thread_state_time[_thread_state] += now - _thread_state_timestamp;
531 if (_thread_state != state)
532 ++_thread_state_count[_thread_state];
533 _thread_state_timestamp = now;
535 _thread_state = state;
540RouterThread::set_thread_state_for_blocking(
int delay_type)
543 set_thread_state(S_BLOCKED);
545 set_thread_state(delay_type ? S_TIMERWAIT : S_PAUSED);
548#if CLICK_DEBUG_SCHEDULING > 1
550RouterThread::thread_state_time(
int state)
const
552 assert(state >= 0 && state < NSTATES);
553 return _thread_state_time[state];
557RouterThread::thread_state_count(
int state)
const
559 assert(state >= 0 && state < NSTATES);
560 return _thread_state_count[state];
A router configuration.
Definition router.hh:28
A set of Tasks scheduled on the same CPU.
Definition routerthread.hh:32
Task * task_next(Task *task) const
Returns the task following task in the scheduled task list.
Definition routerthread.hh:364
Master * master() const
Returns this thread's associated Master.
Definition routerthread.hh:298
int thread_id() const
Returns this thread's ID.
Definition routerthread.hh:291
Task * task_begin() const
Returns the beginning of the scheduled task list.
Definition routerthread.hh:345
bool active() const
Returns whether any tasks are scheduled.
Definition routerthread.hh:311
Task * task_end() const
Returns the end of the scheduled task list.
Definition routerthread.hh:381
A recursive spinlock for SMP Click threads.
Definition sync.hh:439
A spinlock that disables interrupts.
Definition sync.hh:697
A string of characters.
Definition string.hh:22
Represents a frequently-scheduled computational task.
Definition task.hh:49
Represents a moment or interval in time.
Definition timestamp.hh:125
static Timestamp now()
Return the current system time.
Definition timestamp.hh:958
Vector template.
Definition vector.hh:111
T & unchecked_at(size_type i)
Return a reference to the ith element.
Definition vector.hh:350
size_type size() const
Return the number of elements.
Definition vector.hh:231
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
bool compare_and_swap(uint32_t expected, uint32_t desired) CLICK_BUILTINS_NONDEPRECATED
Perform a compare-and-swap operation.
Definition atomic.hh:734
Definition multithread.hh:284
Click's classes for supporting exponentially weighted moving averages.
Classes for synchronizing among multiple CPUs, particularly in the Linux kernel.
Click's vector container template.