From be9cb908306a7cf14033aafb63fcea168600eaab Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Tue, 4 Oct 2011 21:25:56 +0400 Subject: [PATCH] Add "fake" shared memory segment implementation. "Fake" shared memory segments are enabled #if a system does not support POSIX shared memory. Such segments use regular new to allocate memory, it is not shared among multiple processes. The purpose of the change is to allow code that uses Ipc::Mem::Segment to run in non-SMP mode (that is when only a single process, except for master, is running) on systems without POSIX shared memory support. Note: running SHM-using features in SMP mode still requires POSIX shared memory support, the patch does not change that. --- src/ipc/mem/Segment.cc | 110 ++++++++++++++++++++++++++++++++++------- src/ipc/mem/Segment.h | 18 +++++-- 2 files changed, 105 insertions(+), 23 deletions(-) diff --git a/src/ipc/mem/Segment.cc b/src/ipc/mem/Segment.cc index 98c393ce3c..5702fd0f6a 100644 --- a/src/ipc/mem/Segment.cc +++ b/src/ipc/mem/Segment.cc @@ -16,8 +16,24 @@ #include #include +void * +Ipc::Mem::Segment::reserve(size_t chunkSize) +{ + Must(theMem); + // check for overflows + // chunkSize >= 0 may result in warnings on systems where off_t is unsigned + assert(!chunkSize || static_cast(chunkSize) > 0); + assert(static_cast(chunkSize) <= theSize); + assert(theReserved <= theSize - static_cast(chunkSize)); + void *result = reinterpret_cast(theMem) + theReserved; + theReserved += chunkSize; + return result; +} + +#if HAVE_SHM + Ipc::Mem::Segment::Segment(const char *const id): - theName(GenerateName(id)), theFD(-1), theMem(NULL), + theFD(-1), theName(GenerateName(id)), theMem(NULL), theSize(0), theReserved(0), doUnlink(false) { } @@ -33,14 +49,11 @@ Ipc::Mem::Segment::~Segment() unlink(); } +// fake Ipc::Mem::Segment::Enabled (!HAVE_SHM) is more selective bool Ipc::Mem::Segment::Enabled() { -#if HAVE_SHM return true; -#else - return false; -#endif } void @@ -135,20 +148,6 @@ Ipc::Mem::Segment::unlink() debugs(54, 3, HERE << "unlinked " << theName << " segment"); } -void * -Ipc::Mem::Segment::reserve(size_t chunkSize) -{ - Must(theMem); - // check for overflows - // chunkSize >= 0 may result in warnings on systems where off_t is unsigned - assert(!chunkSize || static_cast(chunkSize) > 0); - assert(static_cast(chunkSize) <= theSize); - assert(theReserved <= theSize - static_cast(chunkSize)); - void *result = reinterpret_cast(theMem) + theReserved; - theReserved += chunkSize; - return result; -} - /// determines the size of the underlying "file" off_t Ipc::Mem::Segment::statSize(const char *context) const @@ -184,3 +183,76 @@ Ipc::Mem::Segment::GenerateName(const char *id) name.append(id); return name; } + +#else // HAVE_SHM + +#include + +typedef std::map SegmentMap; +static SegmentMap Segments; + +Ipc::Mem::Segment::Segment(const char *const id): + theName(id), theMem(NULL), theSize(0), theReserved(0), doUnlink(false) +{ +} + +Ipc::Mem::Segment::~Segment() +{ + if (doUnlink) { + delete [] static_cast(theMem); + debugs(54, 3, HERE << "deleted " << theName << " segment"); + } +} + +bool +Ipc::Mem::Segment::Enabled() +{ + return !InDaemonMode() || (!UsingSmp() && IamWorkerProcess()); +} + +void +Ipc::Mem::Segment::create(const off_t aSize) +{ + assert(aSize > 0); + assert(!theMem); + checkSupport("Fake segment creation"); + + const bool inserted = Segments.insert(std::make_pair(theName, this)).second; + if (!inserted) + fatalf("Duplicate fake segment creation: %s", theName.termedBuf()); + + theMem = new char[aSize]; + theSize = aSize; + doUnlink = true; + + debugs(54, 3, HERE << "created " << theName << " fake segment: " << theSize); +} + +void +Ipc::Mem::Segment::open() +{ + assert(!theMem); + checkSupport("Fake segment open"); + + const SegmentMap::const_iterator i = Segments.find(theName); + if (i == Segments.end()) + fatalf("Fake segment not found: %s", theName.termedBuf()); + + const Segment &segment = *i->second; + theMem = segment.theMem; + theSize = segment.theSize; + + debugs(54, 3, HERE << "opened " << theName << " fake segment: " << theSize); +} + +void +Ipc::Mem::Segment::checkSupport(const char *const context) +{ + if (!Enabled()) { + debugs(54, 5, HERE << "True shared memory segments are not supported. " + "Cannot fake shared segments in SMP config."); + fatalf("%s failed", context); + } +} + +#endif // HAVE_SHM diff --git a/src/ipc/mem/Segment.h b/src/ipc/mem/Segment.h index 138de2b98c..b82ac4fab7 100644 --- a/src/ipc/mem/Segment.h +++ b/src/ipc/mem/Segment.h @@ -36,6 +36,13 @@ public: private: + + // not implemented + Segment(const Segment &); + Segment &operator =(const Segment &); + +#if HAVE_SHM + void attach(); void detach(); void unlink(); ///< unlink the segment @@ -43,12 +50,15 @@ private: static String GenerateName(const char *id); - // not implemented - Segment(const Segment &); - Segment &operator =(const Segment &); + int theFD; ///< shared memory segment file descriptor + +#else // HAVE_SHM + + void checkSupport(const char *const context); + +#endif // HAVE_SHM const String theName; ///< shared memory segment file name - int theFD; ///< shared memory segment file descriptor void *theMem; ///< pointer to mmapped shared memory segment off_t theSize; ///< shared memory segment size off_t theReserved; ///< the total number of reserve()d bytes -- 2.47.3