28#include <flow/util/util.hpp>
29#include <flow/util/stat/stat_set.hpp>
84 using flow::util::ceil_div;
118 &&
"Metadata area must fit within the 1st quantum; see allocate() doc header.");
119 fill_n(bitmap_words_start,
161 unsigned int zero_bit_idx{};
164 auto bitmap_words_addr = find_if(search_start, search_end,
167 static_assert(
sizeof(
bit_word_t) ==
sizeof(
long long),
168 "We assume that `long long` is 64-bits, as our stuff is 64-bits, and we use __builtin_ffsll()");
169 return (zero_bit_idx =
static_cast<unsigned int>(::__builtin_ffsll(
static_cast<int64_t
>(~bits)))) != 0;
171 if (zero_bit_idx == 0)
173 assert((bitmap_words_addr == search_end) &&
"Bug in above search?!");
176 bitmap_words_addr = find_if(bitmap_words_start, search_start,
179 return (zero_bit_idx =
static_cast<unsigned int>(::__builtin_ffsll(
static_cast<int64_t
>(~bits)))) != 0;
181 if (zero_bit_idx == 0)
183 assert((bitmap_words_addr == search_start) &&
"Bug in above search?!");
198 &&
"Did we not static_assert() that m_bitmap_words is evenly divided?");
207 const auto bitmap_words_idx = bitmap_words_addr - bitmap_words_start;
210 const auto mask =
bit_word_t(1) << (zero_bit_idx - 1);
211 assert(((*bitmap_words_addr & mask) ==
bit_word_t(0)) &&
"Did we mess up the above logic/use of intrinsic?");
213 *bitmap_words_addr |= mask;
229 const auto addr = data_start
230 + (((bitmap_words_idx *
sizeof(
bit_word_t) * 8) + zero_bit_idx - 1)
233 &&
"alloc() returning invalid addr: out of range.");
239 const auto addr =
reinterpret_cast<uint8_t*
>(void_addr);
246 const auto data_start =
reinterpret_cast<uint8_t*
>(
this) + m_header.m_data_start_minus_this;
248 if (addr == data_start)
256 assert((addr >= data_start) &&
"Invalid dealloc(addr): addr out of range (too low).");
257 auto offset_from_data_start =
static_cast<size_t>(addr - data_start);
260 assert(((offset_from_data_start % S_ALLOC_SZ) == 0)
261 &&
"Invalid dealloc(addr): addr offset from data_start is not a multiple of ALLOC_SZ.");
262 offset_from_data_start /= S_ALLOC_SZ;
265 assert((offset_from_data_start < S_USE_COUNTS_CAPACITY) &&
"Invalid dealloc(addr): addr out of range (too high).");
267 constexpr size_t BITS_PER_WORD =
sizeof(
bit_word_t) * 8;
268 m_header.m_bitmap_words[offset_from_data_start / BITS_PER_WORD]
269 &= (~(
bit_word_t(1) << (offset_from_data_start % BITS_PER_WORD)));
271 m_header.m_allocated_sz -= S_ALLOC_SZ;
285 using flow::util::stat::fetch_add;
286 using flow::util::stat::update_hi_wmark;
291 if (quanta_active_x_bitmap_qtm_words == prev_quanta_active)
293 return quanta_active_x_bitmap_qtm_words;
295 assert((quanta_active_x_bitmap_qtm_words > prev_quanta_active)
296 &&
"It cannot change and go down; see allocate() et al.");
303 const auto quanta_added =
static_cast<uint64_t
>((quanta_active_x_bitmap_qtm_words - prev_quanta_active)
313 auto inc_sz = quanta_added * INC_PER_QTM_SZ;
317 if (prev_quanta_active == 0)
358 assert((mapped_sz == (((MAX_QUANTA - quanta_added) * INC_PER_QTM_SZ) + inc_sz))
359 &&
"Something is off somewhere... get_min_size()+base_offset() should = all hdr+all quanta.");
364 fetch_add(&target_stats->
m_mapped_sz, mapped_sz) + mapped_sz);
369 return quanta_active_x_bitmap_qtm_words;
374 using flow::util::stat::fetch_sub;
381 if (quanta_active_x_bitmap_qtm_words == 0)
397 mapped_sz - ((MAX_QUANTA - quanta_active)
400 return quanta_active_x_bitmap_qtm_words;
static constexpr size_t get_min_size(size_t extra_hdr_sz)
Size we require at max capacity (all S_USE_COUNTS_CAPACITY times S_ALLOC_SZ bytes used) for the conta...
size_t get_free_memory() const
How many allocate(N) calls, times S_ALLOC_SZ, would succeed now without deallocate() in-between,...
void grow(size_t extra_sz)
No-op: as of this writing a *this will allocate up to S_USE_COUNTS_CAPACITY times S_ALLOC_SZ,...
static constexpr size_t base_offset()
The number of bytes between the start of the SHM-pool (segment) storing us and us (*this).
static constexpr size_t S_BITMAP_QUANTUM_SZ
The size of each bitmap section (in bytes) corresponding to 1 quantum of use-count slots (each N byte...
static constexpr size_t S_USE_COUNTS_CAPACITY_QUANTUM_SZ
The size of each quantum into a whole number of which the data area (sized S_USE_COUNTS_CAPACITY N-by...
Header m_header
See Header doc header.
static constexpr size_t S_ALLOC_SZ
This important constant defines the mandatory size of each allocation – that is argument to allocate(...
void deallocate(void *addr) noexcept
Reverses an earlier allocate() call.
size_t stats_record_at_deletion(Obj_db_aux_pool_stats *target_stats)
Assuming one has followed the required algorithm to update *target_stats so far, this method (intende...
size_t stats_record(size_t prev_quanta_active, Obj_db_aux_pool_stats *target_stats)
Updates the various GAUGEs and HI_WMARKs in *target_stats, if and only if it is appropriate to do so ...
uint64_t bit_word_t
In the bitmap mapping the data area of size S_USE_COUNTS_CAPACITY, this defines a word of bits; a wor...
static constexpr size_t S_BITMAP_SZ
The total size of the bitmap area which uses 1 bit per 1 use-count slot (each N bytes wide) of the da...
void * allocate(size_t sz)
Allocates space out of S_USE_COUNTS_CAPACITY times S_ALLOC_SZ bytes available originally,...
size_t stat_quanta_active() const
Returns a non-negative number that is some compile-time constant K times the number of quanta current...
Use_count_registry(size_t sz, size_t extra_hdr_sz)
Constructs a *this, assumed to be in a SHM-pool (segment) at the time the Sparse_managed_shm is being...
static constexpr size_t S_USE_COUNTS_CAPACITY
Compile-time knob: how many (N-byte) use-counts one *this can allocate.
size_t get_size() const
Returns the value passed to ctor, when the pool was created.
Segregated private stuff for ipc::shm::arena_lend.
Stats about the RAM use of the arena-lending SHM-provider's auxiliary (non-user-data) SHM-pools which...
std::atomic< uint64_t > m_aux_pool_count
Number of aux SHM-pools currently in existence; incremented when a given owner-process thread first e...
std::atomic< uint64_t > m_aux_pool_count_hi_wmark
Max of m_aux_pool_count observed so far.
std::atomic< uint64_t > m_use_ct_quanta_hi_wmark
Max of m_use_ct_quanta observed so far.
std::atomic< uint64_t > m_use_ct_active_quanta_hi_wmark
Max of m_use_ct_active_quanta observed so far.
std::atomic< size_t > m_resident_sz
Of the mapped space tracked (in bytes) in m_mapped_sz, the approximate/ceiling size of resident RAM (...
std::atomic< size_t > m_mapped_sz
Total vaddr space, in bytes, reserved for SHM aux-pools.
std::atomic< uint64_t > m_use_ct_active_quanta
Of the quanta counted in m_use_ct_quanta, count of the ones in active use.
std::atomic< size_t > m_resident_sz_hi_wmark
Max of m_resident_sz observed so far.
std::atomic< size_t > m_mapped_sz_hi_wmark
Max of m_mapped_sz observed so far.
std::atomic< uint64_t > m_use_ct_quanta
Count of quanta available – not necessarily (or typically) all active – across the currently live aux...