From 0b3cecb50af18695def7b58c06f32cbed8d14c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= <vladimir.cunat@nic.cz> Date: Tue, 19 Feb 2019 19:41:19 +0100 Subject: [PATCH] lib/generic/lru: fix alignment of struct lru --- daemon/engine.c | 8 ++++---- lib/generic/lru.c | 10 ++++++++++ lib/generic/lru.h | 1 + lib/utils.c | 12 ++++++++++++ lib/utils.h | 16 ++++++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/daemon/engine.c b/daemon/engine.c index 486bb610c..618a33570 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -576,9 +576,9 @@ static int init_resolver(struct engine *engine) /* Empty init; filled via ./lua/config.lua */ kr_zonecut_init(&engine->resolver.root_hints, (const uint8_t *)"", engine->pool); /* Open NS rtt + reputation cache */ - lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, engine->pool, NULL); - lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, engine->pool, NULL); - lru_create(&engine->resolver.cache_cookie, LRU_COOKIES_SIZE, engine->pool, NULL); + lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, NULL, NULL); + lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, NULL, NULL); + lru_create(&engine->resolver.cache_cookie, LRU_COOKIES_SIZE, NULL, NULL); /* Load basic modules */ engine_register(engine, "iterate", NULL, NULL); @@ -711,7 +711,7 @@ void engine_deinit(struct engine *engine) kr_zonecut_deinit(&engine->resolver.root_hints); kr_cache_close(&engine->resolver.cache); - /* The lru keys are currently malloc-ated and need to be freed. */ + /* The LRUs are currently malloc-ated and need to be freed. */ lru_free(engine->resolver.cache_rtt); lru_free(engine->resolver.cache_rep); lru_free(engine->resolver.cache_cookie); diff --git a/lib/generic/lru.c b/lib/generic/lru.c index 12bba4ed7..98d9033e0 100644 --- a/lib/generic/lru.c +++ b/lib/generic/lru.c @@ -16,6 +16,7 @@ #include "lib/generic/lru.h" #include "contrib/murmurhash3/murmurhash3.h" +#include "contrib/ucw/mempool.h" typedef struct lru_group lru_group_t; @@ -108,6 +109,15 @@ KR_EXPORT struct lru * lru_create_impl(uint max_slots, knot_mm_t *mm_array, knot group_count = 1 << log_groups; assert(max_slots <= group_count * LRU_ASSOC && group_count * LRU_ASSOC < 2 * max_slots); + /* Get a sufficiently aligning mm_array if NULL is passed. */ + if (!mm_array) { + static knot_mm_t mm_array_default = { 0 }; + if (!mm_array_default.ctx) + mm_ctx_init_aligned(&mm_array_default, __alignof(struct lru)); + mm_array = &mm_array_default; + } + assert(mm_array->alloc != mm_malloc && mm_array->alloc != (knot_mm_alloc_t)mp_alloc); + size_t size = offsetof(struct lru, groups[group_count]); struct lru *lru = mm_alloc(mm_array, size); if (unlikely(lru == NULL)) diff --git a/lib/generic/lru.h b/lib/generic/lru.h index b5c9bcd69..1e195c6dc 100644 --- a/lib/generic/lru.h +++ b/lib/generic/lru.h @@ -88,6 +88,7 @@ * @param ptable pointer to a pointer to the LRU * @param max_slots number of slots * @param mm_ctx_array memory context to use for the huge array, NULL for default + * If you pass your own, it needs to produce CACHE_ALIGNED allocations (ubsan). * @param mm_ctx memory context to use for individual key-value pairs, NULL for default * * @note The pointers to memory contexts need to remain valid diff --git a/lib/utils.c b/lib/utils.c index 6e63f9971..09194bf0e 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -71,6 +71,18 @@ void *mm_malloc(void *ctx, size_t n) (void)ctx; return malloc(n); } +void *mm_malloc_aligned(void *ctx, size_t n) +{ + size_t alignment = (size_t)ctx; + void *res; + int err = posix_memalign(&res, alignment, n); + if (err == 0) { + return res; + } else { + assert(err == -1 && errno == ENOMEM); + return NULL; + } +} /* * Macros. diff --git a/lib/utils.h b/lib/utils.h index 8deef4efe..8dabd05da 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -135,6 +135,8 @@ void *mm_realloc(knot_mm_t *mm, void *what, size_t size, size_t prev_size); /** Trivial malloc() wrapper. */ void *mm_malloc(void *ctx, size_t n); +/** posix_memalign() wrapper. */ +void *mm_malloc_aligned(void *ctx, size_t n); /** Initialize mm with standard malloc+free. */ static inline void mm_ctx_init(knot_mm_t *mm) @@ -143,6 +145,20 @@ static inline void mm_ctx_init(knot_mm_t *mm) mm->alloc = mm_malloc; mm->free = free; } + +/** Initialize mm with malloc+free with higher alignment (a power of two). */ +static inline void mm_ctx_init_aligned(knot_mm_t *mm, size_t alignment) +{ + assert(__builtin_popcount(alignment) == 1); + mm->ctx = (uint8_t *)NULL + alignment; /*< roundabout to satisfy linters */ + /* posix_memalign() doesn't allow alignment < sizeof(void*), + * and there's no point in using it for small values anyway, + * as plain malloc() guarantees at least max_align_t. + * Nitpick: we might use that type when assuming C11. */ + mm->alloc = alignment > sizeof(void*) ? mm_malloc_aligned : mm_malloc; + mm->free = free; +} + /* @endcond */ /** A strcmp() variant directly usable for qsort() on an array of strings. */ -- GitLab