diff --git a/include/ircd/allocator.h b/include/ircd/allocator.h index 2a202f254..6d000cc0e 100644 --- a/include/ircd/allocator.h +++ b/include/ircd/allocator.h @@ -46,6 +46,8 @@ namespace ircd::allocator template T set(const string_view &var, T val); bool trim(const size_t &pad = 0) noexcept; // malloc_trim(3) + size_t incore(const const_buffer &); + std::unique_ptr aligned_alloc(const size_t &align, const size_t &size); } @@ -60,6 +62,7 @@ namespace ircd::allocator::je namespace ircd { using allocator::aligned_alloc; + using allocator::incore; } /// Profiling counters. The purpose of this device is to gauge whether unwanted diff --git a/include/ircd/fs/read.h b/include/ircd/fs/read.h index e17561768..ebac6d16e 100644 --- a/include/ircd/fs/read.h +++ b/include/ircd/fs/read.h @@ -29,7 +29,7 @@ namespace ircd::fs std::string read(const fd &, const read_opts & = read_opts_default); // Test whether bytes in the specified range are cached and should not block - bool fincore(const fd &, const size_t &, const read_opts & = read_opts_default); + bool incore(const fd &, const size_t &, const read_opts & = read_opts_default); // Prefetch data for subsequent read(); offset given in opts (WILLNEED). size_t prefetch(const fd &, const size_t &, const read_opts & = read_opts_default); diff --git a/ircd/allocator.cc b/ircd/allocator.cc index 0d8987bd3..f0a8d06b2 100644 --- a/ircd/allocator.cc +++ b/ircd/allocator.cc @@ -9,6 +9,7 @@ // full license for this software is available in the LICENSE file. #include = data(buf) + size(buf)); + const auto span + { + std::distance(base, top) + }; + + const auto above + { + std::distance(end(buf), top) + }; + + assert(span >= 0); + assert(above >= 0); + assert(below >= 0); + assert(above < ssize_t(info::page_size)); + assert(below < ssize_t(info::page_size)); + assert(below + ssize_t(size(buf)) + above == span); + + auto remain(span), ret(0L); + thread_local uint8_t vec alignas(64) [4096]; + for(auto i(0); i < span / ssizeof(vec) && remain > 0; ++i) + { + const auto len + { + std::min(ssizeof(vec) * ssize_t(info::page_size), remain) + }; + + assert(len > 0); + assert(len <= span); + const ssize_t vec_size + ( + std::ceil(len / double(info::page_size)) + ); + + assert(vec_size > 0); + assert(vec_size <= ssizeof(vec)); + syscall(::mincore, mutable_cast(base), len, vec); + for(auto j(0); j < vec_size; ++j) + ret += (vec[j] & 0x01) * info::page_size; + + remain -= len; + assert(remain >= 0); + if(!remain && (vec[vec_size - 1] & 0x01)) // last iteration + ret -= above; + + assert(ret >= 0); + if(i == 0 && (vec[0] & 0x01)) // first iteration + ret -= below; + + assert(ret >= 0); + } + + assert(remain == 0); + assert(ret <= ssize_t(size(buf))); + assert(ret >= 0); + return ret; +} + // // control panel // diff --git a/ircd/fs.cc b/ircd/fs.cc index 05e8b3c01..7ab3c1b94 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -806,11 +806,6 @@ ircd::fs::flush(const fd &fd, // fs/read.h // -namespace ircd::fs -{ - static bool fincore(void *const &map, const size_t &map_size, uint8_t *const &vec, const size_t &vec_size); -} - ircd::fs::read_opts const ircd::fs::read_opts_default {}; @@ -828,13 +823,10 @@ ircd::fs::prefetch(const fd &fd, } bool -ircd::fs::fincore(const fd &fd, - const size_t &count, - const read_opts &opts) +ircd::fs::incore(const fd &fd, + const size_t &count, + const read_opts &opts) { - using word_t = unsigned long long; - thread_local std::array tls_vec; - fs::map::opts map_opts; map_opts.offset = buffer::align(opts.offset, info::page_size); map_opts.blocking = false; @@ -848,44 +840,18 @@ ircd::fs::fincore(const fd &fd, (map_size + info::page_size - 1) / info::page_size }; - const size_t &vec_size - { - std::max(map_pages / sizeof(word_t), 1UL) - }; - - const size_t &dynamic_vec_size - { - vec_size > tls_vec.size()? - vec_size: - 0UL - }; - - std::vector dynamic_vec(dynamic_vec_size); - auto *const vec - { - dynamic_vec_size? - dynamic_vec.data(): - tls_vec.data() - }; - assert(map_opts.offset % 4096 == 0); const fs::map map { fd, map_opts, map_size }; - assert(vec_size > 0 && vec_size <= map_size); - return fincore(data(map), map_size, reinterpret_cast(vec), vec_size); -} + const size_t res + { + allocator::incore(map) + }; -bool -ircd::fs::fincore(void *const &map, - const size_t &map_size, - uint8_t *const &vec, - const size_t &vec_size) -{ - syscall(::mincore, map, map_size, vec); - return std::find(vec, vec + vec_size, 0UL) == vec + vec_size; + return res == map_size; } std::string