Click
Loading...
Searching...
No Matches
master.hh
1// -*- c-basic-offset: 4; related-file-name: "../../lib/master.cc" -*-
2#ifndef CLICK_MASTER_HH
3#define CLICK_MASTER_HH
4#include <click/router.hh>
5#include <click/atomic.hh>
6#if CLICK_USERLEVEL
7# include <signal.h>
8#endif
9#if CLICK_NS
10# include <click/simclick.h>
11#endif
12CLICK_DECLS
13
14#define CLICK_DEBUG_MASTER 0
15
16class Master { public:
17
18 Master(int nthreads);
19 ~Master();
20
21 void use();
22 void unuse();
23
24 void block_all();
25 void unblock_all();
26
27 void pause();
28 inline void unpause();
29 bool paused() const { return _master_paused > 0; }
30
31 inline int nthreads() const;
32 inline RouterThread *thread(int id) const;
33 void wake_somebody();
34
35#if CLICK_USERLEVEL
36 int add_signal_handler(int signo, Router *router, String handler);
37 int remove_signal_handler(int signo, Router *router, String handler);
38 void process_signals(RouterThread *thread);
39 static void signal_handler(int signo); // not really public
40#endif
41
42 void kill_router(Router*);
43
44#if CLICK_NS
45 void initialize_ns(simclick_node_t *simnode);
46 simclick_node_t *simnode() const { return _simnode; }
47#endif
48
49#if CLICK_DEBUG_MASTER || CLICK_DEBUG_SCHEDULING
50 String info() const;
51#endif
52
53#if CLICK_USERLEVEL
54 static volatile sig_atomic_t signals_pending;
55#endif
56
57 private:
58
59 // THREADS
60 RouterThread **_threads;
61 int _nthreads;
62
63 // ROUTERS
64 Router *_routers;
65 int _refcount;
66 void register_router(Router*);
67 void prepare_router(Router*);
68 void run_router(Router*, bool foreground);
69 void unregister_router(Router*);
70
71#if CLICK_LINUXMODULE
72 spinlock_t _master_lock;
73 struct task_struct *_master_lock_task;
74 int _master_lock_count;
75#elif HAVE_MULTITHREAD
76 Spinlock _master_lock;
77#endif
78 atomic_uint32_t _master_paused;
79 inline void lock_master();
80 inline void unlock_master();
81
82 void request_stop();
83 bool verify_stop(RouterThread* t);
84
85#if CLICK_USERLEVEL
86 // SIGNALS
87 struct SignalInfo {
88 int signo;
89 Router *router;
90 String handler;
91 SignalInfo *next;
92 SignalInfo(int signo_, Router *router_, const String &handler_)
93 : signo(signo_), router(router_), handler(handler_), next() {
94 }
95 bool equals(int signo_, Router *router_, const String &handler_) const {
96 return signo == signo_ && router == router_ && handler == handler_;
97 }
98 };
99 SignalInfo *_siginfo;
100 sigset_t _sig_dispatching;
101 Spinlock _signal_lock;
102#endif
103
104#if CLICK_NS
105 simclick_node_t *_simnode;
106#endif
107
108 Master(const Master&);
109 Master& operator=(const Master&);
110
111 friend class Task;
112 friend class RouterThread;
113 friend class Router;
114};
115
116inline int
117Master::nthreads() const
118{
119 return _nthreads - 1;
120}
121
122inline RouterThread*
123Master::thread(int id) const
124{
125 // return the requested thread, or the quiescent thread if there's no such
126 // thread
127 if (unsigned(id + 1) < unsigned(_nthreads))
128 return _threads[id + 1];
129 else
130 return _threads[0];
131}
132
133inline void
134Master::wake_somebody()
135{
136 _threads[1]->wake();
137}
138
139#if CLICK_USERLEVEL
140inline void
141RouterThread::run_signals()
142{
143 if (Master::signals_pending)
144 _master->process_signals(this);
145}
146
147inline int
148TimerSet::next_timer_delay(bool more_tasks, Timestamp &t) const
149{
150# if CLICK_NS
151 // The simulator should never block.
152 (void) more_tasks, (void) t;
153 return 0;
154# else
155 if (more_tasks || Master::signals_pending)
156 return 0;
157 t = timer_expiry_steady_adjusted();
158 if (!t)
159 return -1; // block forever
160#if TIMESTAMP_WARPABLE
161 else if (unlikely(Timestamp::warp_jumping())) {
162 Timestamp::warp_jump_steady(t);
163 return 0;
164 }
165#endif
166 else if ((t -= Timestamp::now_steady(), !t.is_negative())) {
167#if TIMESTAMP_WARPABLE
168 t = t.warp_real_delay();
169#endif
170 return 1;
171 } else
172 return 0;
173# endif
174}
175#endif
176
177inline void
178Master::request_stop()
179{
180 for (RouterThread **t = _threads; t != _threads + _nthreads; ++t)
181 (*t)->_stop_flag = true;
182 // ensure that at least one thread is awake to handle the stop event
183 wake_somebody();
184}
185
186inline void
187Master::lock_master()
188{
189#if CLICK_LINUXMODULE
190 if (current != _master_lock_task) {
191 spin_lock(&_master_lock);
192 _master_lock_task = current;
193 } else
194 _master_lock_count++;
195#elif HAVE_MULTITHREAD
196 _master_lock.acquire();
197#endif
198}
199
200inline void
201Master::unlock_master()
202{
203#if CLICK_LINUXMODULE
204 assert(current == _master_lock_task);
205 if (_master_lock_count == 0) {
206 _master_lock_task = 0;
207 spin_unlock(&_master_lock);
208 } else
209 _master_lock_count--;
210#elif HAVE_MULTITHREAD
211 _master_lock.release();
212#endif
213}
214
215inline void
216Master::unpause()
217{
218 _master_paused--;
219}
220
221inline Master *
223{
224 return _router->master();
225}
226
227CLICK_ENDDECLS
228#endif
An atomic 32-bit integer.
Master * master() const
Return the element's master.
Definition master.hh:222
A router configuration.
Definition router.hh:28
Master * master() const
Return the Master object for this router.
Definition router.hh:591
A set of Tasks scheduled on the same CPU.
Definition routerthread.hh:32
A recursive spinlock for SMP Click threads.
Definition sync.hh:439
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_steady()
Return the current steady-clock time.
Definition timestamp.hh:986
bool is_negative() const
Test if this Timestamp is negative (< Timestamp(0, 0)).
Definition timestamp.hh:228
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
The Router class implementing a router configuration.