openflow build environment setup
This commit is contained in:
223
openflow/include/click/master.hh
Normal file
223
openflow/include/click/master.hh
Normal file
@ -0,0 +1,223 @@
|
||||
// -*- c-basic-offset: 4; related-file-name: "../../lib/master.cc" -*-
|
||||
#ifndef CLICK_MASTER_HH
|
||||
#define CLICK_MASTER_HH
|
||||
#include <click/router.hh>
|
||||
#include <click/atomic.hh>
|
||||
#if CLICK_USERLEVEL
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#if CLICK_NS
|
||||
# include <click/simclick.h>
|
||||
#endif
|
||||
CLICK_DECLS
|
||||
|
||||
#define CLICK_DEBUG_MASTER 0
|
||||
|
||||
class Master { public:
|
||||
|
||||
Master(int nthreads);
|
||||
~Master();
|
||||
|
||||
void use();
|
||||
void unuse();
|
||||
|
||||
void block_all();
|
||||
void unblock_all();
|
||||
|
||||
void pause();
|
||||
inline void unpause();
|
||||
bool paused() const { return _master_paused > 0; }
|
||||
|
||||
inline int nthreads() const;
|
||||
inline RouterThread *thread(int id) const;
|
||||
void wake_somebody();
|
||||
|
||||
#if CLICK_USERLEVEL
|
||||
int add_signal_handler(int signo, Router *router, String handler);
|
||||
int remove_signal_handler(int signo, Router *router, String handler);
|
||||
void process_signals(RouterThread *thread);
|
||||
static void signal_handler(int signo); // not really public
|
||||
#endif
|
||||
|
||||
void kill_router(Router*);
|
||||
|
||||
#if CLICK_NS
|
||||
void initialize_ns(simclick_node_t *simnode);
|
||||
simclick_node_t *simnode() const { return _simnode; }
|
||||
#endif
|
||||
|
||||
#if CLICK_DEBUG_MASTER || CLICK_DEBUG_SCHEDULING
|
||||
String info() const;
|
||||
#endif
|
||||
|
||||
#if CLICK_USERLEVEL
|
||||
static volatile sig_atomic_t signals_pending;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// THREADS
|
||||
RouterThread **_threads;
|
||||
int _nthreads;
|
||||
|
||||
// ROUTERS
|
||||
Router *_routers;
|
||||
int _refcount;
|
||||
void register_router(Router*);
|
||||
void prepare_router(Router*);
|
||||
void run_router(Router*, bool foreground);
|
||||
void unregister_router(Router*);
|
||||
|
||||
#if CLICK_LINUXMODULE
|
||||
spinlock_t _master_lock;
|
||||
struct task_struct *_master_lock_task;
|
||||
int _master_lock_count;
|
||||
#elif HAVE_MULTITHREAD
|
||||
Spinlock _master_lock;
|
||||
#endif
|
||||
atomic_uint32_t _master_paused;
|
||||
inline void lock_master();
|
||||
inline void unlock_master();
|
||||
|
||||
void request_stop();
|
||||
bool verify_stop(RouterThread* t);
|
||||
|
||||
#if CLICK_USERLEVEL
|
||||
// SIGNALS
|
||||
struct SignalInfo {
|
||||
int signo;
|
||||
Router *router;
|
||||
String handler;
|
||||
SignalInfo *next;
|
||||
SignalInfo(int signo_, Router *router_, const String &handler_)
|
||||
: signo(signo_), router(router_), handler(handler_), next() {
|
||||
}
|
||||
bool equals(int signo_, Router *router_, const String &handler_) const {
|
||||
return signo == signo_ && router == router_ && handler == handler_;
|
||||
}
|
||||
};
|
||||
SignalInfo *_siginfo;
|
||||
sigset_t _sig_dispatching;
|
||||
Spinlock _signal_lock;
|
||||
#endif
|
||||
|
||||
#if CLICK_NS
|
||||
simclick_node_t *_simnode;
|
||||
#endif
|
||||
|
||||
Master(const Master&);
|
||||
Master& operator=(const Master&);
|
||||
|
||||
friend class Task;
|
||||
friend class RouterThread;
|
||||
friend class Router;
|
||||
};
|
||||
|
||||
inline int
|
||||
Master::nthreads() const
|
||||
{
|
||||
return _nthreads - 1;
|
||||
}
|
||||
|
||||
inline RouterThread*
|
||||
Master::thread(int id) const
|
||||
{
|
||||
// return the requested thread, or the quiescent thread if there's no such
|
||||
// thread
|
||||
if (unsigned(id + 1) < unsigned(_nthreads))
|
||||
return _threads[id + 1];
|
||||
else
|
||||
return _threads[0];
|
||||
}
|
||||
|
||||
inline void
|
||||
Master::wake_somebody()
|
||||
{
|
||||
_threads[1]->wake();
|
||||
}
|
||||
|
||||
#if CLICK_USERLEVEL
|
||||
inline void
|
||||
RouterThread::run_signals()
|
||||
{
|
||||
if (Master::signals_pending)
|
||||
_master->process_signals(this);
|
||||
}
|
||||
|
||||
inline int
|
||||
TimerSet::next_timer_delay(bool more_tasks, Timestamp &t) const
|
||||
{
|
||||
# if CLICK_NS
|
||||
// The simulator should never block.
|
||||
(void) more_tasks, (void) t;
|
||||
return 0;
|
||||
# else
|
||||
if (more_tasks || Master::signals_pending)
|
||||
return 0;
|
||||
t = timer_expiry_steady_adjusted();
|
||||
if (!t)
|
||||
return -1; // block forever
|
||||
else if (unlikely(Timestamp::warp_jumping())) {
|
||||
Timestamp::warp_jump_steady(t);
|
||||
return 0;
|
||||
} else if ((t -= Timestamp::now_steady(), !t.is_negative())) {
|
||||
t = t.warp_real_delay();
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void
|
||||
Master::request_stop()
|
||||
{
|
||||
for (RouterThread **t = _threads; t != _threads + _nthreads; ++t)
|
||||
(*t)->_stop_flag = true;
|
||||
// ensure that at least one thread is awake to handle the stop event
|
||||
wake_somebody();
|
||||
}
|
||||
|
||||
inline void
|
||||
Master::lock_master()
|
||||
{
|
||||
#if CLICK_LINUXMODULE
|
||||
if (current != _master_lock_task) {
|
||||
spin_lock(&_master_lock);
|
||||
_master_lock_task = current;
|
||||
} else
|
||||
_master_lock_count++;
|
||||
#elif HAVE_MULTITHREAD
|
||||
_master_lock.acquire();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
Master::unlock_master()
|
||||
{
|
||||
#if CLICK_LINUXMODULE
|
||||
assert(current == _master_lock_task);
|
||||
if (_master_lock_count == 0) {
|
||||
_master_lock_task = 0;
|
||||
spin_unlock(&_master_lock);
|
||||
} else
|
||||
_master_lock_count--;
|
||||
#elif HAVE_MULTITHREAD
|
||||
_master_lock.release();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
Master::unpause()
|
||||
{
|
||||
_master_paused--;
|
||||
}
|
||||
|
||||
inline Master *
|
||||
Element::master() const
|
||||
{
|
||||
return _router->master();
|
||||
}
|
||||
|
||||
CLICK_ENDDECLS
|
||||
#endif
|
||||
Reference in New Issue
Block a user