const int64_t entryLimit = MemStore::EntryLimit();
assert(entryLimit > 0);
+
+ Ipc::Mem::PageStack::Config spaceConfig;
+ spaceConfig.poolId = Ipc::Mem::PageStack::IdForMemStoreSpace(),
+ spaceConfig.pageSize = 0; // the pages are stored in Ipc::Mem::Pages
+ spaceConfig.capacity = entryLimit;
+ spaceConfig.createFull = true; // all pages are initially available
Must(!spaceOwner);
- spaceOwner = shm_new(Ipc::Mem::PageStack)(SpaceLabel,
- Ipc::Mem::PageStack::IdForMemStoreSpace(),
- entryLimit, 0);
+ spaceOwner = shm_new(Ipc::Mem::PageStack)(SpaceLabel, spaceConfig);
Must(!mapOwner);
mapOwner = MemStoreMap::Init(MapLabel, entryLimit);
Must(!extrasOwner);
mapOwners.push_back(mapOwner);
// TODO: somehow remove pool id and counters from PageStack?
+ Ipc::Mem::PageStack::Config config;
+ config.poolId = Ipc::Mem::PageStack::IdForSwapDirSpace(i);
+ config.pageSize = 0; // this is an index of slots on _disk_
+ config.capacity = capacity;
+ config.createFull = false; // Rebuild finds and pushes free slots
Ipc::Mem::Owner<Ipc::Mem::PageStack> *const freeSlotsOwner =
- shm_new(Ipc::Mem::PageStack)(sd->freeSlotsPath(),
- Ipc::Mem::PageStack::IdForSwapDirSpace(i),
- capacity,
- 0);
+ shm_new(Ipc::Mem::PageStack)(sd->freeSlotsPath(), config);
freeSlotsOwners.push_back(freeSlotsOwner);
-
- // TODO: add method to initialize PageStack with no free pages
- while (true) {
- Ipc::Mem::PageId pageId;
- if (!freeSlotsOwner->object()->pop(pageId))
- break;
- }
}
}
}
Ipc::Mem::PagePool::Owner *
Ipc::Mem::PagePool::Init(const char *const shmId, const Ipc::Mem::PoolId stackId, const unsigned int capacity, const size_t pageSize)
{
- return shm_new(PageStack)(shmId, stackId, capacity, pageSize);
+ PageStack::Config config;
+ config.poolId = stackId;
+ config.pageSize = pageSize; // the pages are stored in Ipc::Mem::Pages
+ config.capacity = capacity;
+ config.createFull = true; // all pages are initially available
+ return shm_new(PageStack)(shmId, config);
}
Ipc::Mem::PagePool::PagePool(const char *const id):
// atomic wrappers in nodes_ must be zero-size. Check the best we can. Once.
static_assert(sizeof(StoredNode) == sizeof(Node), "atomic locks use no storage");
assert(StoredNode().is_lock_free());
-
- makeFullBeforeSharing();
}
void
/* Ipc::Mem::PageStack */
-Ipc::Mem::PageStack::PageStack(const PoolId aPoolId, const PageCount aCapacity, const size_t aPageSize):
- thePoolId(aPoolId), capacity_(aCapacity), thePageSize(aPageSize),
+Ipc::Mem::PageStack::PageStack(const Config &config):
+ config_(config),
size_(0),
- ids_(capacity_)
+ ids_(config_.capacity)
{
- size_ = capacity_;
+ if (config.createFull) {
+ ids_.makeFullBeforeSharing();
+ size_ = config_.capacity;
+ }
}
bool
{
assert(!page);
- if (!capacity_)
+ if (!config_.capacity)
return false;
IdSet::size_type pageIndex = 0;
// must decrement after removing the page to avoid underflow
const auto newSize = --size_;
- assert(newSize < capacity_);
+ assert(newSize < config_.capacity);
page.number = pageIndex + 1;
- page.pool = thePoolId;
+ page.pool = config_.poolId;
debugs(54, 8, page << " size: " << newSize);
assert(pageIdIsValid(page));
return true;
// must increment before inserting the page to avoid underflow in pop()
const auto newSize = ++size_;
- assert(newSize <= capacity_);
+ assert(newSize <= config_.capacity);
const auto pageIndex = page.number - 1;
ids_.push(pageIndex);
bool
Ipc::Mem::PageStack::pageIdIsValid(const PageId &page) const
{
- return page.pool == thePoolId &&
+ return page.pool == config_.poolId &&
0 < page.number && page.number <= capacity();
}
size_t
Ipc::Mem::PageStack::sharedMemorySize() const
{
- return SharedMemorySize(thePoolId, capacity_, thePageSize);
+ return SharedMemorySize(config_);
}
size_t
-Ipc::Mem::PageStack::SharedMemorySize(const PoolId, const PageCount capacity, const size_t pageSize)
+Ipc::Mem::PageStack::SharedMemorySize(const Config &cfg)
{
const auto levelsSize = PageId::maxPurpose * sizeof(Levels_t);
- const size_t pagesDataSize = capacity * pageSize;
- return StackSize(capacity) + LevelsPaddingSize(capacity) + levelsSize + pagesDataSize;
+ const size_t pagesDataSize = cfg.capacity * cfg.pageSize;
+ return StackSize(cfg.capacity) + pagesDataSize + levelsSize;
}
size_t
size_t
Ipc::Mem::PageStack::stackSize() const
{
- return StackSize(capacity_);
+ return StackSize(config_.capacity);
}
size_t
/// the number of (free and/or used) pages in a stack
typedef unsigned int PageCount;
- PageStack(const PoolId aPoolId, const PageCount aCapacity, const size_t aPageSize);
+ // XXX: poolId, pageSize look misplaced due to messy separation of PagePool
+ // (which should support multiple Segments but does not) and PageStack
+ // (which should not calculate the Segment size but does) duties.
+ /// PageStack construction and SharedMemorySize calculation parameters
+ class Config {
+ public:
+ uint32_t poolId = 0; ///< pool ID
+ size_t pageSize = 0; ///< page size, used to calculate shared memory size
+ PageCount capacity = 0; ///< the maximum number of pages
+
+ /// whether a newly created PageStack should be prefilled with PageIds
+ bool createFull = false;
+ };
- PageCount capacity() const { return capacity_; }
- size_t pageSize() const { return thePageSize; }
+ explicit PageStack(const Config &);
+
+ PageCount capacity() const { return config_.capacity; }
+ size_t pageSize() const { return config_.pageSize; }
/// an approximate number of free pages
PageCount size() const { return size_.load(); }
bool pageIdIsValid(const PageId &page) const;
/// total shared memory size required to share
- static size_t SharedMemorySize(const PoolId aPoolId, const PageCount capacity, const size_t pageSize);
+ static size_t SharedMemorySize(const Config &);
size_t sharedMemorySize() const;
/// shared memory size required only by PageStack, excluding
/// \returns the number of padding bytes to align PagePool::theLevels array
static size_t LevelsPaddingSize(const PageCount capacity);
- size_t levelsPaddingSize() const { return LevelsPaddingSize(capacity_); }
+ size_t levelsPaddingSize() const { return LevelsPaddingSize(config_.capacity); }
/**
* The following functions return PageStack IDs for the corresponding
static PoolId IdForSwapDirSpace(const int dirIdx) { return 900 + dirIdx + 1; }
private:
- // XXX: theFoo members look misplaced due to messy separation of PagePool
- // (which should support multiple Segments but does not) and PageStack
- // (which should not calculate the Segment size but does) duties.
- const PoolId thePoolId; ///< pool ID
- const PageCount capacity_; ///< the maximum number of pages
- const size_t thePageSize; ///< page size, used to calculate shared memory size
+ const Config config_;
/// a lower bound for the number of free pages (for debugging purposes)
std::atomic<PageCount> size_;