*
*/
-#include "config.h"
+#include "squid.h"
#include "base/TextException.h"
+#include "base/RunnersRegistry.h"
#include "ipc/mem/PagePool.h"
#include "ipc/mem/Pages.h"
#include "structs.h"
// Eventually, we may have pools dedicated to memory caching, disk I/O, etc.
// TODO: make pool id more unique so it does not conflict with other Squids?
-static const String PagePoolId = "squid-page-pool";
+static const char *PagePoolId = "squid-page-pool";
static Ipc::Mem::PagePool *ThePagePool = 0;
+static int TheLimits[Ipc::Mem::PageId::maxPurpose];
-// XXX: temporary function until we have a better page size handling
-static unsigned int
-calculatePageSize()
+// TODO: make configurable to avoid waste when mem-cached objects are small/big
+size_t
+Ipc::Mem::PageSize()
{
- unsigned int max_objsize = 0;
- for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
- const SwapDir *const sd = dynamic_cast<SwapDir *>(INDEXSD(i));
- if (sd->max_objsize > max_objsize)
- max_objsize = sd->max_objsize;
- }
- return max_objsize;
+ return 32*1024;
}
-void
-Ipc::Mem::Init()
+bool
+Ipc::Mem::GetPage(const PageId::Purpose purpose, PageId &page)
{
- Must(!ThePagePool);
- // XXX: pool capacity and page size should be configurable/meaningful
- ThePagePool = new PagePool(PagePoolId, 1024, calculatePageSize());
+ return ThePagePool && PagesAvailable(purpose) > 0 ?
+ ThePagePool->get(purpose, page) : false;
}
void
-Ipc::Mem::Attach()
+Ipc::Mem::PutPage(PageId &page)
{
- Must(!ThePagePool);
- // TODO: make pool id more unique so it does not conflict with other Squid instances?
- ThePagePool = new PagePool(PagePoolId);
+ Must(ThePagePool);
+ ThePagePool->put(page);
}
-bool
-Ipc::Mem::GetPage(PageId &page)
+char *
+Ipc::Mem::PagePointer(const PageId &page)
{
Must(ThePagePool);
- return ThePagePool->get(page);
+ return ThePagePool->pagePointer(page);
+}
+
+size_t
+Ipc::Mem::PageLimit()
+{
+ size_t limit = 0;
+ for (int i = 0; i < PageId::maxPurpose; ++i)
+ limit += PageLimit(i);
+ return limit;
+}
+
+size_t
+Ipc::Mem::PageLimit(const int purpose)
+{
+ Must(0 <= purpose && purpose <= PageId::maxPurpose);
+ return TheLimits[purpose];
}
+// note: adjust this if we start recording needs during reconfigure
void
-Ipc::Mem::PutPage(PageId &page)
+Ipc::Mem::NotePageNeed(const int purpose, const int count)
{
- Must(ThePagePool);
- ThePagePool->put(page);
+ Must(0 <= purpose && purpose <= PageId::maxPurpose);
+ Must(count >= 0);
+ TheLimits[purpose] += count;
}
-void *
-Ipc::Mem::PagePointer(const PageId &page)
+size_t
+Ipc::Mem::PageLevel()
{
- Must(ThePagePool);
- return ThePagePool->pagePointer(page);
+ return ThePagePool ? ThePagePool->level() : 0;
+}
+
+size_t
+Ipc::Mem::PageLevel(const int purpose)
+{
+ return ThePagePool ? ThePagePool->level(purpose) : 0;
+}
+
+/// initializes shared memory pages
+class SharedMemPagesRr: public Ipc::Mem::RegisteredRunner
+{
+public:
+ /* RegisteredRunner API */
+ SharedMemPagesRr(): owner(NULL) {}
+ virtual void run(const RunnerRegistry &);
+ virtual void create(const RunnerRegistry &);
+ virtual void open(const RunnerRegistry &);
+ virtual ~SharedMemPagesRr();
+
+private:
+ Ipc::Mem::PagePool::Owner *owner;
+};
+
+RunnerRegistrationEntry(rrAfterConfig, SharedMemPagesRr);
+
+
+void
+SharedMemPagesRr::run(const RunnerRegistry &r)
+{
+ if (Ipc::Mem::PageLimit() <= 0)
+ return;
+
+ Ipc::Mem::RegisteredRunner::run(r);
+}
+
+void
+SharedMemPagesRr::create(const RunnerRegistry &)
+{
+ Must(!owner);
+ owner = Ipc::Mem::PagePool::Init(PagePoolId, Ipc::Mem::PageLimit(),
+ Ipc::Mem::PageSize());
+}
+
+void
+SharedMemPagesRr::open(const RunnerRegistry &)
+{
+ Must(!ThePagePool);
+ ThePagePool = new Ipc::Mem::PagePool(PagePoolId);
+}
+
+SharedMemPagesRr::~SharedMemPagesRr()
+{
+ if (!UsingSmp())
+ return;
+
+ delete ThePagePool;
+ ThePagePool = NULL;
+ delete owner;
}