Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251return addr;252}253void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len)254{255len = align_up(len, page_size);256memory_cleanse(addr, len);257munlock(addr, len);258munmap(addr, len);259}260size_t PosixLockedPageAllocator::GetLimit()261{262#ifdef RLIMIT_MEMLOCK263struct rlimit rlim;264if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) {265if (rlim.rlim_cur != RLIM_INFINITY &&266std::cmp_less_equal(rlim.rlim_cur, static_cast<rlim_t>(std::numeric_limits<size_t>::max()))) {267return rlim.rlim_cur;268}269}270#endif271return std::numeric_limits<size_t>::max();272}273#endif275/*******************************************************************************/276// Implementation: LockedPool278LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, LockingFailed_Callback lf_cb_in)279: allocator(std::move(allocator_in)), lf_cb(lf_cb_in)280{281}283LockedPool::~LockedPool() = default;285void* LockedPool::alloc(size_t size)286{287std::lock_guard<std::mutex> lock(mutex);289// Don't handle impossible sizes290if (size == 0 || size > ARENA_SIZE)291return nullptr;293// Try allocating from each current arena294for (auto &arena: arenas) {295void *addr = arena.alloc(size);296if (addr) {297return addr;298}299}300// If that fails, create a new one301if (new_arena(ARENA_SIZE, ARENA_ALIGN)) {302return arenas.back().alloc(size);303}304return nullptr;305}307void LockedPool::free(void *ptr)308{309std::lock_guard<std::mutex> lock(mutex);310// TODO we can do better than this linear search by keeping a map of arena311// extents to arena, and looking up the address.312for (auto &arena: arenas) {313if (arena.addressInArena(ptr)) {314arena.free(ptr);315return;316}317}318throw std::runtime_error("LockedPool: invalid address not pointing to any arena");319}321LockedPool::Stats LockedPool::stats() const322{323std::lock_guard<std::mutex> lock(mutex);324LockedPool::Stats r{0, 0, 0, cumulative_bytes_locked, 0, 0};325for (const auto &arena: arenas) {326Arena::Stats i = arena.stats();327r.used += i.used;328r.free += i.free;329r.total += i.total;330r.chunks_used += i.chunks_used;331r.chunks_free += i.chunks_free;332}333return r;334}336bool LockedPool::new_arena(size_t size, size_t align)337{338bool locked;339// If this is the first arena, handle this specially: Cap the upper size340// by the process limit. This makes sure that the first arena will at least341// be locked. An exception to this is if the process limit is 0:342// in this case no memory can be locked at all so we'll skip past this logic.343if (arenas.empty()) {344size_t limit = allocator->GetLimit();345if (limit > 0) {346size = std::min(size, limit);347}348}349void *addr = allocator->AllocateLocked(size, &locked);350if (!addr) {351return false;352}353if (locked) {354cumulative_bytes_locked += size;355} else if (lf_cb) { // Call the locking-failed callback if locking failed356if (!lf_cb()) { // If the callback returns false, free the memory and fail, otherwise consider the user warned and proceed.357allocator->FreeLocked(addr, size);358return false;359}360}361arenas.emplace_back(allocator.get(), addr, size, align);362return true;363}365LockedPool::LockedPageArena::LockedPageArena(LockedPageAllocator *allocator_in, void *base_in, size_t size_in, size_t align_in):366Arena(base_in, size_in, align_in), base(base_in), size(size_in), allocator(allocator_in)367{368}369LockedPool::LockedPageArena::~LockedPageArena()370{371allocator->FreeLocked(base, size);372}374/*******************************************************************************/375// Implementation: LockedPoolManager376//377LockedPoolManager::LockedPoolManager(std::unique_ptr<LockedPageAllocator> allocator_in):378LockedPool(std::move(allocator_in), &LockedPoolManager::LockingFailed)379{380}382bool LockedPoolManager::LockingFailed()383{384// TODO: log something but how? without including util.h385return true;386}388void LockedPoolManager::CreateInstance()389{390// Using a local static instance guarantees that the object is initialized391// when it's first needed and also deinitialized after all objects that use392// it are done with it. I can think of one unlikely scenario where we may393// have a static deinitialization order/problem, but the check in394// LockedPoolManagerBase's destructor helps us detect if that ever happens.395#ifdef WIN32396std::unique_ptr<LockedPageAllocator> allocator(new Win32LockedPageAllocator());397#else398std::unique_ptr<LockedPageAllocator> allocator(new PosixLockedPageAllocator());399#endif400static LockedPoolManager instance(std::move(allocator));401LockedPoolManager::_instance = &instance;402}404LockedPoolManager& LockedPoolManager::Instance()405{406static std::once_flag init_flag;407std::call_once(init_flag, LockedPoolManager::CreateInstance);408return *LockedPoolManager::_instance;409}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.