Add memcpy with bounds checks.

The memcpy implementation is not completely stupid but is almost
certainly not as good as a carefully tuned and optimised one.

Building snmalloc with FreeBSD's libc memcpy + jemalloc and with this,
each 10 times, does not show a statistically significant performance
difference at 95% confidence.  The snmalloc version has very slightly
lower median and worst-case times.  This is in no way a sensible
benchmark, but it serves as a smoke test for significant performance
regressions.

The CI self-host job now uses the checked memcpy.

This also fixes an off-by-one error in the external bounds.  This is
triggered by ninja, so we will see breakage in CI if it is reintroduced.

In debug builds, we provide a verbose error containing the address of
the allocation, the base and bounds of the allocation, and a backtrace.

The backtrace was broken by the CI cleanup moving the BACKTRACE_HEADER
macro into the SNMALLOC_ namespace.  This is also fixed.

The test involves hijacking `abort`, which doesn't work everywhere.  It
also requires `backtrace` to work in configurations where stack traces
are enabled.  This is disabled in QEMU because `backtrace` appears to
crash reliably in QEMU user mode.

For now, in the -checks build configurations, we are hitting a slow path
in the pagemap on accesses so that the pages that are `PROT_NONE` don't
cause crashes.  These need to be made read-only, but this requires a PAL
change.
This commit is contained in:
David Chisnall
2021-08-10 11:36:53 +01:00
committed by David Chisnall
parent d524ef5cac
commit 51e75bca89
12 changed files with 482 additions and 59 deletions

View File

@@ -231,11 +231,11 @@ namespace snmalloc
* expected to point to the base of some (sub)allocation into which cursor
* points; would-be negative answers trip an assertion in debug builds.
*/
inline size_t pointer_diff(void* base, void* cursor)
inline size_t pointer_diff(const void* base, const void* cursor)
{
SNMALLOC_ASSERT(cursor >= base);
return static_cast<size_t>(
static_cast<char*>(cursor) - static_cast<char*>(base));
static_cast<const char*>(cursor) - static_cast<const char*>(base));
}
template<

View File

@@ -15,6 +15,7 @@
# define SNMALLOC_PURE
# define SNMALLOC_COLD
# define SNMALLOC_REQUIRE_CONSTINIT
# define SNMALLOC_UNUSED_FUNCTION
#else
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
@@ -25,6 +26,7 @@
# define SNMALLOC_FAST_PATH_LAMBDA SNMALLOC_FAST_PATH
# define SNMALLOC_PURE __attribute__((const))
# define SNMALLOC_COLD __attribute__((cold))
# define SNMALLOC_UNUSED_FUNCTION __attribute((unused))
# ifdef __clang__
# define SNMALLOC_REQUIRE_CONSTINIT \
[[clang::require_constant_initialization]]