Skip to content
Snippets Groups Projects
Commit 7e1a5c23 authored by Martin Karsten's avatar Martin Karsten
Browse files

- roll main fibre/processor/cluster into event scope (renamed from event engine)

- cache context pointers to cluster, poller, event scope in TLS
parent 4b02c772
No related branches found
No related tags found
No related merge requests found
......@@ -26,15 +26,15 @@
#include <sys/socket.h>
class EventScope {
typedef Mutex<SystemLock> EventLock;
typedef FifoSemaphore<BinaryLock<1,1>,true> EventSemaphore; // only two competitors, no backoff needed
MasterPoller masterPoller; // runs without cluster
TimerQueue timerQueue; // scope-global timer queue
// A vector for FDs works well here in principle, because POSIX guarantees lowest-numbered FDs:
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_14
// A fixed-size array based on 'getrlimit' is somewhat brute-force, but simple and fast.
struct SyncIO {
EventLock lock;
EventSemaphore sem;
Mutex<SystemLock> lock;
FifoSemaphore<BinaryLock<1,1>,true> sem; // only two competitors, no backoff needed
void reset() { lock.acquire(); sem.reset(); lock.release(); }
};
......@@ -49,23 +49,36 @@ class EventScope {
// file operations are not considered blocking in terms of select/poll/epoll
// therefore, all file operations are executed on dedicated Cluster/SP(s)
DiskCluster diskCluster;
SystemProcessor diskProcessor;
DiskCluster diskCluster;
SystemProcessor diskProcessor;
TimerQueue timerQueue;
// main cluster, processor. fibre
FibreCluster* mainCluster;
SystemProcessor* mainProcessor;
Fibre* mainFibre;
MasterPoller masterPoller; // runs without cluster
public:
EventScope() : fdSyncVector(0), diskCluster(*this, 0), diskProcessor(diskCluster), masterPoller(*this) {
EventScope() : masterPoller(*this), diskCluster(*this, 0), diskProcessor(diskCluster) {
// start event demultiplexing & timer handling
struct rlimit rl;
SYSCALL(getrlimit(RLIMIT_NOFILE, &rl)); // get hard limit for file descriptor count
fdcount = masterPoller.initTimerHandling(rl.rlim_max);
fdSyncVector = new SyncRW[fdcount]; // create vector of R and W sync points
masterPoller.start();
// create default cluster -> includes poller
mainCluster = new FibreCluster(*this);
// create main processor
mainProcessor = new SystemProcessor(*mainCluster, _friend<EventScope>());
// create main fibre and main SP's idle fibre using dedicated interface
mainFibre = mainProcessor->init(_friend<EventScope>());
}
public:
EventScope(_friend<_Bootstrapper>) : EventScope() {}
~EventScope() {
delete mainFibre;
delete mainProcessor;
delete mainCluster;
delete[] fdSyncVector;
}
......
......@@ -86,16 +86,4 @@ public:
typedef FibreClusterGeneric<ClusterPoller> FibreCluster;
typedef FibreClusterGeneric<NoPoller> DiskCluster;
static inline FibreCluster& CurrCluster() {
return reinterpret_cast<FibreCluster&>(CurrProcessor().getCluster());
}
static inline ClusterPoller& CurrPoller() {
return CurrCluster().getPoller();
}
static inline EventScope& CurrEventScope() {
return CurrPoller().getEventScope();
}
#endif /* _FibreCluster_h_ */
......@@ -20,7 +20,7 @@ ifeq ($(CC),clang)
CXX=clang++
else
CXX=g++
CXXFLAGS+=-fno-extern-tls-init
CFGFLAGS+=-fno-extern-tls-init
endif
AS=as
......@@ -36,7 +36,7 @@ CXXFLAGS=$(LANGFLAGS) $(OPTFLAGS) $(DBGFLAGS) $(COMPFLAGS) $(CFGFLAGS)
PREFLAGS=$(LANGFLAGS) $(OPTFLAGS) $(COMPFLAGS) $(KERNFLAGS) $(CFGFLAGS)
#SPLITSTACK=-fsplit-stack -DSPLIT_STACK
CXXFLAGS+=-fpic $(SPLITSTACK)
CXXFLAGS+=-fPIC $(SPLITSTACK)
ifneq ($(OPTIM),1)
#CXXFLAGS+=-fsanitize=address # and/or other -fsanitize options
......
......@@ -29,20 +29,20 @@ class Fibre;
template<typename> class FibreClusterGeneric;
class BasePoller {
protected:
EventScope& eventScope;
public: // RegistrationStatus
static const int Read = 0x1;
static const int Write = 0x2;
protected:
static const int maxPoll = 1024;
static const int maxPoll = 256;
#if __FreeBSD__
struct kevent events[maxPoll];
#else // __linux__ below
epoll_event events[maxPoll];
#endif
EventScope& eventScope;
int pollFD;
volatile bool pollTerminate;
volatile bool paused;
......
......@@ -23,11 +23,17 @@
// instance definitions for Context members
thread_local StackContext* volatile Context::currStack = nullptr; // lfbasics.h
thread_local SystemProcessor* volatile Context::currProc = nullptr; // lfbasics.h
thread_local FibreCluster* volatile Context::currCluster = nullptr; // lfbasics.h
thread_local ClusterPoller* volatile Context::currPoller = nullptr; // lfbasics.h
thread_local EventScope* volatile Context::currScope = nullptr; // lfbasics.h
// noinline routines for Context
void Context::setCurrStack(StackContext& s, _friend<Runtime>) { currStack = &s; }
StackContext* Context::CurrStack() { return currStack; }
SystemProcessor* Context::CurrProc() { return currProc; }
StackContext* Context::CurrStack() { return currStack; }
SystemProcessor* Context::CurrProcessor() { return currProc; }
FibreCluster* Context::CurrCluster() { return currCluster; }
ClusterPoller* Context::CurrPoller() { return currPoller; }
EventScope* Context::CurrEventScope() { return currScope; }
SystemProcessor::SystemProcessor(Cluster& cluster, funcvoid1_t func, ptr_t arg) : BaseProcessor(cluster), terminateAck(false) {
sysThread = pthread_self();
......@@ -51,14 +57,18 @@ SystemProcessor::SystemProcessor(Cluster& cluster) : BaseProcessor(cluster), ter
SYSCALL(pthread_attr_destroy(&attr));
}
SystemProcessor::SystemProcessor() : SystemProcessor(CurrCluster()) {}
SystemProcessor::SystemProcessor() : SystemProcessor(::CurrCluster()) {}
SystemProcessor::SystemProcessor(Cluster& cluster, _friend<_Bootstrapper>) : BaseProcessor(cluster), terminateAck(false) {
SystemProcessor::SystemProcessor(Cluster& cluster, _friend<EventScope>) : BaseProcessor(cluster), terminateAck(false) {
sysThread = pthread_self(); // main pthread runs main routine
Context::currProc = this;
FibreCluster* fc = reinterpret_cast<FibreCluster*>(&cluster);
Context::currCluster = fc;
Context::currPoller = &fc->getPoller();
Context::currScope = &fc->getPoller().getEventScope();
}
Fibre* SystemProcessor::init(_friend<_Bootstrapper>) {
Fibre* SystemProcessor::init(_friend<EventScope>) {
// create proper idle loop fibre
setupIdle(new Fibre(*this, defaultStackSize, _friend<SystemProcessor>()));
idleStack->setup((ptr_t)idleLoopSetupFibre, this);
......@@ -69,17 +79,20 @@ Fibre* SystemProcessor::init(_friend<_Bootstrapper>) {
}
void SystemProcessor::setupFakeContext(StackContext* sc, _friend<BasePoller>) {
Context::currProc = nullptr;
Context::currStack = sc;
Context::currProc = nullptr;
Context::currCluster = nullptr;
Context::currPoller = nullptr;
Context::currScope = nullptr;
}
SystemProcessor::~SystemProcessor() {
terminate = true; // no more work added, idle terminating
wakeUp(); // wake up idle loop (just in case)
terminateSem.P(); // wait for acknowledgement from idle loop
if (this == &CurrProcessor()) { // make sure current fibre is off this processor
if (this == Context::CurrProcessor()) { // make sure current fibre is off this processor
Fibre::migrateSelf(cluster);
GENASSERT(this != &CurrProcessor());
GENASSERT(this != Context::CurrProcessor());
}
wakeUp(); // wake up idle loop (just in case)
delete (Fibre*)idleStack; // wait for idle loop to finish
......@@ -112,6 +125,10 @@ void SystemProcessor::idleLoopSetupFibre(void* sp) {
inline void SystemProcessor::idleLoopRunFibre() {
Context::currProc = this;
FibreCluster* fc = reinterpret_cast<FibreCluster*>(&cluster);
Context::currCluster = fc;
Context::currPoller = &fc->getPoller();
Context::currScope = &fc->getPoller().getEventScope();
// idle loop takes over pthread stack - create fibre without stack
setupIdle(new Fibre(*this, _friend<SystemProcessor>()));
Context::currStack = idleStack;
......
......@@ -46,9 +46,9 @@ public:
SystemProcessor(Cluster& cluster);
// dedicated constructor for bootstrap
SystemProcessor(Cluster& cluster, _friend<_Bootstrapper>);
SystemProcessor(Cluster& cluster, _friend<EventScope>);
// dedicated initialization routine for bootstrap
Fibre* init(_friend<_Bootstrapper>);
Fibre* init(_friend<EventScope>);
// dedicated support routine to set up dummy context for poller pthreads
static void setupFakeContext(StackContext* sc, _friend<BasePoller>);
......@@ -63,10 +63,4 @@ public:
}
};
static inline SystemProcessor& CurrProcessor() {
SystemProcessor* proc = Context::CurrProc();
GENASSERT(proc);
return *proc;
}
#endif /* _SystemProcessor_h_ */
......@@ -243,6 +243,10 @@ inline void dprintl(const Args&... a) {
struct Runtime;
class StackContext;
class SystemProcessor;
class ClusterPoller;
template<typename> class FibreClusterGeneric;
typedef FibreClusterGeneric<ClusterPoller> FibreCluster;
class EventScope;
// it seems noinline is needed for TLS and then volatile is free anyway...
// http://stackoverflow.com/questions/25673787/making-thread-local-variables-fully-volatile
......@@ -251,10 +255,16 @@ class Context {
protected: // definitions and initialization are in SystemProcessor.cc
static thread_local StackContext* volatile currStack;
static thread_local SystemProcessor* volatile currProc;
static thread_local FibreCluster* volatile currCluster;
static thread_local ClusterPoller* volatile currPoller;
static thread_local EventScope* volatile currScope;
public:
static void setCurrStack(StackContext& s, _friend<Runtime>) __no_inline;
static StackContext* CurrStack() __no_inline;
static SystemProcessor* CurrProc() __no_inline;
static StackContext* CurrStack() __no_inline;
static SystemProcessor* CurrProcessor() __no_inline;
static FibreCluster* CurrCluster() __no_inline;
static ClusterPoller* CurrPoller() __no_inline;
static EventScope* CurrEventScope() __no_inline;
};
static inline StackContext* CurrStack() {
......@@ -263,6 +273,29 @@ static inline StackContext* CurrStack() {
return s;
}
static inline SystemProcessor& CurrProcessor() {
SystemProcessor* p = Context::CurrProcessor();
GENASSERT(p);
return *p;
}
static inline FibreCluster& CurrCluster() {
FibreCluster* c = Context::CurrCluster();
GENASSERT(c);
return *c;
}
static inline ClusterPoller& CurrPoller() {
ClusterPoller* p = Context::CurrPoller();
GENASSERT(p);
return *p;
}
static inline EventScope& CurrEventScope() {
EventScope* e = Context::CurrEventScope();
GENASSERT(e);
return *e;
}
// **** global constants
#ifdef SPLIT_STACK
......
......@@ -22,16 +22,14 @@
// global pointers
SystemLock* _lfDebugOutputLock = nullptr; // lfbasics.h
// default EventScope object
static EventScope* _lfEventScope = nullptr;
#if TESTING_ENABLE_DEBUGGING
SystemLock* _globalStackLock = nullptr; // StackContext.h
GlobalStackList* _globalStackList = nullptr; // StackContext.h
#endif
// make these pointers global static to enable gdb access
static Fibre* _lfMainFibre = nullptr;
static SystemProcessor* _lfMainProcessor = nullptr;
static FibreCluster* _lfMainCluster = nullptr;
#if TESTING_ENABLE_STATISTICS
std::list<StatsObject*>* StatsObject::lst = nullptr;
#endif
......@@ -59,22 +57,14 @@ _Bootstrapper::_Bootstrapper() {
_globalStackLock = new SystemLock;
_globalStackList = new GlobalStackList;
#endif
// start event demultiplexing & timer handling
EventScope* eventScope = new EventScope;
// create default cluster -> includes poller
_lfMainCluster = new FibreCluster(*eventScope);
// create main SP
_lfMainProcessor = new SystemProcessor(*_lfMainCluster, _friend<_Bootstrapper>());
// create main fibre and main SP's idle fibre using dedicated interface
_lfMainFibre = _lfMainProcessor->init(_friend<_Bootstrapper>());
// bootstrap system via event scope
_lfEventScope = new EventScope(_friend<_Bootstrapper>());
}
}
_Bootstrapper::~_Bootstrapper() {
if (--counter == 0) {
// delete _lfMainFibre;
// delete _lfMainProcessor;
// delete _lfMainCluster;
// delete _lfEventScope
delete _lfDebugOutputLock;
#if TESTING_ENABLE_DEBUGGING
delete _globalStackList;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment