diff --git a/src/libfibre/EventScope.h b/src/libfibre/EventScope.h index d7f7f9932033393e11ad8362740eb007e685dd57..aa1afd93c7237a5cc09face5d9101a8a688531ae 100644 --- a/src/libfibre/EventScope.h +++ b/src/libfibre/EventScope.h @@ -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; } diff --git a/src/libfibre/FibreCluster.h b/src/libfibre/FibreCluster.h index fff993e800977e043375f64c5121a743b3c33562..b97e2419c083a97a1252af7b5aeedc506ce939d1 100644 --- a/src/libfibre/FibreCluster.h +++ b/src/libfibre/FibreCluster.h @@ -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_ */ diff --git a/src/libfibre/Makefile b/src/libfibre/Makefile index 1380ff33df1cc2c817c5faf482e9cb8cff477fe7..8848d05573a6cdd225f2721028778cdc910b336b 100644 --- a/src/libfibre/Makefile +++ b/src/libfibre/Makefile @@ -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 diff --git a/src/libfibre/Poller.h b/src/libfibre/Poller.h index 9dc8be2fdff03c7da999454f53c23580f46afd7d..3c8110fae301f1073316bdaa337d56e66641099d 100644 --- a/src/libfibre/Poller.h +++ b/src/libfibre/Poller.h @@ -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; diff --git a/src/libfibre/SystemProcessor.cc b/src/libfibre/SystemProcessor.cc index bbcae8f202c9e549129733326662c66e2645d65e..5ccd0429249b6350d45b2d74fc2422ddeaa5e73b 100644 --- a/src/libfibre/SystemProcessor.cc +++ b/src/libfibre/SystemProcessor.cc @@ -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; diff --git a/src/libfibre/SystemProcessor.h b/src/libfibre/SystemProcessor.h index f85d94e4d5664c9ce5219ef3c0aceedc0e085a5f..cbe64690cb22dfa07e7ac2fd76424af11a578ab2 100644 --- a/src/libfibre/SystemProcessor.h +++ b/src/libfibre/SystemProcessor.h @@ -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_ */ diff --git a/src/libfibre/lfbasics.h b/src/libfibre/lfbasics.h index 250d836768869c824b3a348e21728ee9f189da1b..7ae6611c6d94cd86132586469a5ac4210db1b2d9 100644 --- a/src/libfibre/lfbasics.h +++ b/src/libfibre/lfbasics.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 diff --git a/src/libfibre/lfcore.cc b/src/libfibre/lfcore.cc index a98d248db37c0dddbc6d4443a9ae5df53c83e73e..cbd567abd87334982d73900241419b6c95faf1ac 100644 --- a/src/libfibre/lfcore.cc +++ b/src/libfibre/lfcore.cc @@ -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;