]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
mempool: pull in simplified version from Knot DNS
authorPetr Špaček <petr.spacek@nic.cz>
Mon, 19 Aug 2019 14:17:57 +0000 (16:17 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Mon, 26 Aug 2019 13:13:06 +0000 (15:13 +0200)
Function kr_pkt_text was only user of mp_printf functions, so these were
removed to simplify code.

Assumption is that kr_pkt_text is used only for debugging and is not
optimized for speed - in the worst case it needs to convert data to text
representation twice.

36 files changed:
.gitlab-ci.yml
bench/bench_lru.c
contrib/asan.h [new file with mode: 0644]
contrib/macros.h [new file with mode: 0644]
contrib/meson.build
contrib/ucw/alloc.h [deleted file]
contrib/ucw/config.h [deleted file]
contrib/ucw/lib.h [deleted file]
contrib/ucw/mempool-fmt.c [deleted file]
contrib/ucw/mempool.c
contrib/ucw/mempool.h
daemon/io.c
daemon/session.c
daemon/session.h
daemon/tls.c
daemon/udp_queue.c
daemon/worker.c
lib/cache/api.c
lib/cache/api.h
lib/cache/cdb_lmdb.c
lib/cache/entry_pkt.c
lib/cache/knot_pkt.c
lib/cache/nsec1.c
lib/cache/nsec3.c
lib/cache/peek.c
lib/defines.h
lib/generic/lru.c
lib/generic/lru.h
lib/generic/queue.c
lib/generic/queue.h
lib/generic/trie.c
lib/layer/iterate.c
lib/nsrep.c
lib/resolve.c
lib/utils.c
lib/zonecut.c

index 4e81c2ddd0b80990a16d59ab682b7749b42e955f..5339aad2cbd0488e568f8fbca0a9674584773e33 100644 (file)
@@ -226,7 +226,7 @@ lint:scan-build:
   script:
     - export SCANBUILD="scan-build --status-bugs -no-failure-reports $(./scripts/get-scanbuild-args.sh)"
     - ninja -C build_ci* scan-build || true
-    - test "$(ls build_ci*/meson-logs/scanbuild/*/report-*.html | wc -l)" = 29 # we have this many errors ATM :-)
+    - test "$(ls build_ci*/meson-logs/scanbuild/*/report-*.html | wc -l)" = 27 # we have this many errors ATM :-)
 
 lint:tidy:
   <<: *test
index 237be669387431a0c023a80f90fa58b1d96fb43a..04313a85cfdaf309cce7be548eaebe6bb9549cd4 100644 (file)
@@ -21,7 +21,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 
-#include "contrib/ucw/lib.h"
+#include "contrib/macros.h"
 #include "daemon/engine.h"
 #include "lib/nsrep.h"
 
diff --git a/contrib/asan.h b/contrib/asan.h
new file mode 100644 (file)
index 0000000..5feb2c1
--- /dev/null
@@ -0,0 +1,37 @@
+/*  Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/*
+ * see sanitizer/asan_interface.h in compiler-rt (LLVM)
+ */
+#ifndef __has_feature
+  #define __has_feature(feature) 0
+#endif
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+  void __asan_poison_memory_region(void const volatile *addr, size_t size);
+  void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+  #define ASAN_POISON_MEMORY_REGION(addr, size) \
+    __asan_poison_memory_region((addr), (size))
+  #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
+    __asan_unpoison_memory_region((addr), (size))
+#else
+  #define ASAN_POISON_MEMORY_REGION(addr, size) \
+    ((void)(addr), (void)(size))
+  #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
+    ((void)(addr), (void)(size))
+#endif
diff --git a/contrib/macros.h b/contrib/macros.h
new file mode 100644 (file)
index 0000000..2e80c45
--- /dev/null
@@ -0,0 +1,48 @@
+/*  Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*!
+ * \brief Common macros.
+ */
+
+#pragma once
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#ifndef MIN
+/*! \brief Type-safe minimum macro. */
+#define MIN(a, b) \
+       __extension__({ \
+               __typeof__ (a) _amin = (a); \
+               __typeof__ (b) _bmin = (b); \
+               _amin < _bmin ? _amin : _bmin; })
+
+/*! \brief Type-safe maximum macro. */
+#define MAX(a, b) \
+       __extension__({ \
+               __typeof__ (a) _amax = (a); \
+               __typeof__ (b) _bmax = (b); \
+               _amax > _bmax ? _amax : _bmax; })
+#endif
+
+#ifndef likely
+/*! \brief Optimize for x to be true value. */
+#define likely(x) __builtin_expect((x), 1)
+#endif
+
+#ifndef unlikely
+/*! \brief Optimize for x to be false value. */
+#define unlikely(x) __builtin_expect((x), 0)
+#endif
index e69d01754a4eed42ca91c32da7564501f39829f8..47268a35659497fc943562382609b59d43cb4f60 100644 (file)
@@ -5,7 +5,6 @@ contrib_src = files([
   'ccan/ilog/ilog.c',
   'ccan/json/json.c',
   'ucw/mempool.c',
-  'ucw/mempool-fmt.c',
   'murmurhash3/murmurhash3.c',
   'base32hex.c',
   'base64.c'
diff --git a/contrib/ucw/alloc.h b/contrib/ucw/alloc.h
deleted file mode 100644 (file)
index 668c707..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *     UCW Library -- Generic allocators
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#ifndef _UCW_ALLOC_H
-#define _UCW_ALLOC_H
-
-/**
- * This structure describes a generic allocator. It provides pointers
- * to three functions, which handle the actual (re)allocations.
- **/
-struct ucw_allocator {
-  void * (*alloc)(struct ucw_allocator *alloc, size_t size);
-  void * (*realloc)(struct ucw_allocator *alloc, void *ptr, size_t old_size, size_t new_size);
-  void (*free)(struct ucw_allocator *alloc, void *ptr);
-};
-
-/* alloc-std.c */
-
-/**
- * [[std]]
- * This allocator uses <<basics:xmalloc()>>, <<basics:xrealloc()>> and <<basics:xfree()>>. The memory
- * it allocates is left unitialized.
- **/
-extern struct ucw_allocator ucw_allocator_std;
-
-/**
- * [[zeroing]]
- * This allocator uses <<basics:xmalloc()>>, <<basics:xrealloc()>> and <<basics:xfree()>>. All memory
- * is zeroed upon allocation.
- **/
-extern struct ucw_allocator ucw_allocator_zeroed;
-
-#endif
diff --git a/contrib/ucw/config.h b/contrib/ucw/config.h
deleted file mode 100644 (file)
index 5d3cb4f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *     UCW Library -- Configuration-Dependent Definitions
- *
- *     (c) 1997--2012 Martin Mares <mj@ucw.cz>
- *     (c) 2006 Robert Spalek <robert@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#ifndef _UCW_CONFIG_H
-#define _UCW_CONFIG_H
-
-/* Default page size and pointer alignment */
-#ifndef CPU_PAGE_SIZE
-#define CPU_PAGE_SIZE 4096
-#endif
-#define CPU_STRUCT_ALIGN sizeof(void *)
-
-/* Tell libc we're going to use all extensions available */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-/* Types (based on standard C99 integers) */
-
-#include <stddef.h>
-#include <stdint.h>
-
-typedef uint8_t byte;                  /** Exactly 8 bits, unsigned **/
-typedef uint8_t u8;                    /** Exactly 8 bits, unsigned **/
-typedef int8_t s8;                     /** Exactly 8 bits, signed **/
-typedef uint16_t u16;                  /** Exactly 16 bits, unsigned **/
-typedef int16_t s16;                   /** Exactly 16 bits, signed **/
-typedef uint32_t u32;                  /** Exactly 32 bits, unsigned **/
-typedef int32_t s32;                   /** Exactly 32 bits, signed **/
-typedef uint64_t u64;                  /** Exactly 64 bits, unsigned **/
-typedef int64_t s64;                   /** Exactly 64 bits, signed **/
-
-
-#ifndef uint /* Redefining typedef is a C11 feature. */
-typedef unsigned int uint;             /** A better pronounceable alias for `unsigned int` **/
-#define uint uint
-#endif
-
-typedef s64 timestamp_t;               /** Milliseconds since an unknown epoch **/
-
-// FIXME: This should be removed soon
-typedef uint uns;                      /** Backwards compatible alias for `uint' ***/
-
-#ifdef CONFIG_UCW_LARGE_FILES
-typedef s64 ucw_off_t;                 /** File position (either 32- or 64-bit, depending on `CONFIG_UCW_LARGE_FILES`). **/
-#else
-typedef s32 ucw_off_t;
-#endif
-
-#endif
diff --git a/contrib/ucw/lib.h b/contrib/ucw/lib.h
deleted file mode 100644 (file)
index 506f09b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *     The UCW Library -- Miscellaneous Functions
- *
- *     (c) 1997--2014 Martin Mares <mj@ucw.cz>
- *     (c) 2005--2014 Tomas Valla <tom@ucw.cz>
- *     (c) 2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2007 Pavel Charvat <pchar@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#ifndef _UCW_LIB_H
-#define _UCW_LIB_H
-
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#ifdef CONFIG_UCW_CLEAN_ABI
-#define assert_failed ucw_assert_failed
-#define assert_failed_msg ucw_assert_failed_msg
-#define assert_failed_noinfo ucw_assert_failed_noinfo
-#define big_alloc ucw_big_alloc
-#define big_alloc_zero ucw_big_alloc_zero
-#define big_free ucw_big_free
-#define die ucw_die
-#define log_die_hook ucw_log_die_hook
-#define log_file ucw_log_file
-#define log_fork ucw_log_fork
-#define log_init ucw_log_init
-#define log_pid ucw_log_pid
-#define log_title ucw_log_title
-#define msg ucw_msg
-#define page_alloc ucw_page_alloc
-#define page_alloc_zero ucw_page_alloc_zero
-#define page_free ucw_page_free
-#define page_realloc ucw_page_realloc
-#define random_max ucw_random_max
-#define random_max_u64 ucw_random_max_u64
-#define random_u32 ucw_random_u32
-#define random_u64 ucw_random_u64
-#define vdie ucw_vdie
-#define vmsg ucw_vmsg
-#define xfree ucw_xfree
-#define xmalloc ucw_xmalloc
-#define xmalloc_zero ucw_xmalloc_zero
-#define xrealloc ucw_xrealloc
-#define xstrdup ucw_xstrdup
-#endif
-
-/*** === Macros for handling structures, offsets and alignment ***/
-
-#define CHECK_PTR_TYPE(x, type) ((x)-(type)(x) + (type)(x))            /** Check that a pointer @x is of type @type. Fail compilation if not. **/
-#define PTR_TO(s, i) &((s*)0)->i                                       /** Return OFFSETOF() in form of a pointer. **/
-#define OFFSETOF(s, i) ((uint)offsetof(s, i))                          /** Offset of item @i from the start of structure @s **/
-#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))         /** Given a pointer @p to item @i of structure @s, return a pointer to the start of the struct. **/
-
-/** Align an integer @s to the nearest higher multiple of @a (which should be a power of two) **/
-#define ALIGN_TO(s, a) (((s)+a-1)&~(a-1))
-
-/** Align a pointer @p to the nearest higher multiple of @s. **/
-#define ALIGN_PTR(p, s) ((uintptr_t)(p) % (s) ? (typeof(p))((uintptr_t)(p) + (s) - (uintptr_t)(p) % (s)) : (p))
-
-#define UNALIGNED_PART(ptr, type) (((uintptr_t) (ptr)) % sizeof(type))
-
-/*** === Other utility macros ***/
-
-#define MIN(a,b) (((a)<(b))?(a):(b))                   /** Minimum of two numbers **/
-#define MAX(a,b) (((a)>(b))?(a):(b))                   /** Maximum of two numbers **/
-#define CLAMP(x,min,max) ({ typeof(x) _t=x; (_t < min) ? min : (_t > max) ? max : _t; })       /** Clip a number @x to interval [@min,@max] **/
-#define ABS(x) ((x) < 0 ? -(x) : (x))                  /** Absolute value **/
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))         /** The number of elements of an array **/
-#define STRINGIFY(x) #x                                        /** Convert macro parameter to a string **/
-#define STRINGIFY_EXPANDED(x) STRINGIFY(x)             /** Convert an expanded macro parameter to a string **/
-#define GLUE(x,y) x##y                                 /** Glue two tokens together **/
-#define GLUE_(x,y) x##_##y                             /** Glue two tokens together, separating them by an underscore **/
-
-#define COMPARE(x,y) do { if ((x)<(y)) return -1; if ((x)>(y)) return 1; } while(0)            /** Numeric comparison function for qsort() **/
-#define REV_COMPARE(x,y) COMPARE(y,x)                                                          /** Reverse numeric comparison **/
-#define COMPARE_LT(x,y) do { if ((x)<(y)) return 1; if ((x)>(y)) return 0; } while(0)
-#define COMPARE_GT(x,y) COMPARE_LT(y,x)
-
-#define        ROL(x, bits) (((x) << (bits)) | ((uint)(x) >> (sizeof(uint)*8 - (bits))))               /** Bitwise rotation of an unsigned int to the left **/
-#define        ROR(x, bits) (((uint)(x) >> (bits)) | ((x) << (sizeof(uint)*8 - (bits))))               /** Bitwise rotation of an unsigned int to the right **/
-
-/*** === Shortcuts for GCC Extensions ***/
-
-#ifdef __GNUC__
-
-#include "ccan/compiler/compiler.h"
-#define FORMAT_CHECK(x,y,z) __attribute__((format(x,y,z)))             /** Checking of printf-like format strings **/
-#define likely(x) __builtin_expect((x),1)                              /** Use `if (likely(@x))` if @x is almost always true **/
-#define unlikely(x) __builtin_expect((x),0)                            /** Use `if (unlikely(@x))` to hint that @x is almost always false **/
-
-#if __GNUC__ >= 4 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3
-#define ALWAYS_INLINE inline __attribute__((always_inline))            /** Forcibly inline **/
-#define NO_INLINE __attribute__((noinline))                            /** Forcibly uninline **/
-#else
-#define ALWAYS_INLINE inline
-#endif
-
-#if __GNUC__ >= 4
-#define LIKE_MALLOC __attribute__((malloc))                            /** Function returns a "new" pointer **/
-#define SENTINEL_CHECK __attribute__((sentinel))                       /** The last argument must be NULL **/
-#else
-#define LIKE_MALLOC
-#define SENTINEL_CHECK
-#endif
-
-#else
-#error This program requires the GNU C compiler.
-#endif
-
-/***
- * [[logging]]
- *
- * === Basic logging functions (see <<log:,Logging>> and <ucw/log.h> for more)
- ***/
-
-#define DBG(x, ...) do { } while(0)
-#define DBG_SPOT do { } while(0)
-#define ASSERT(x)
-
-#endif
diff --git a/contrib/ucw/mempool-fmt.c b/contrib/ucw/mempool-fmt.c
deleted file mode 100644 (file)
index 6c93e1e..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  UCW Library -- Memory Pools (Formatting)
- *
- *  (c) 2005 Martin Mares <mj@ucw.cz>
- *  (c) 2007 Pavel Charvat <pchar@ucw.cz>
- *
- *  This software may be freely distributed and used according to the terms
- *  of the GNU Lesser General Public License.
- */
-
-#include <ucw/lib.h>
-#include <ucw/mempool.h>
-
-#include <stdio.h>
-#include <string.h>
-
-/* FIXME: migrate to Knot DNS version of mempools. */
-#pragma GCC diagnostic ignored "-Wpointer-arith"
-
-static char *
-mp_vprintf_at(struct mempool *mp, size_t ofs, const char *fmt, va_list args)
-{
-  char *ret = mp_grow(mp, ofs + 1) + ofs;
-  va_list args2;
-  va_copy(args2, args);
-  int cnt = vsnprintf(ret, mp_avail(mp) - ofs, fmt, args2);
-  va_end(args2);
-  if (cnt < 0)
-    {
-      /* Our C library doesn't support C99 return value of vsnprintf, so we need to iterate */
-      do
-  {
-    ret = mp_expand(mp) + ofs;
-    va_copy(args2, args);
-    cnt = vsnprintf(ret, mp_avail(mp) - ofs, fmt, args2);
-    va_end(args2);
-  }
-      while (cnt < 0);
-    }
-  else if ((uint)cnt >= mp_avail(mp) - ofs)
-    {
-      ret = mp_grow(mp, ofs + cnt + 1) + ofs;
-      va_copy(args2, args);
-      vsnprintf(ret, cnt + 1, fmt, args2);
-      va_end(args2);
-    }
-  mp_end(mp, ret + cnt + 1);
-  return ret - ofs;
-}
-
-char *
-mp_vprintf(struct mempool *mp, const char *fmt, va_list args)
-{
-  mp_start(mp, 1);
-  return mp_vprintf_at(mp, 0, fmt, args);
-}
-
-char *
-mp_printf(struct mempool *p, const char *fmt, ...)
-{
-  va_list args;
-  va_start(args, fmt);
-  char *res = mp_vprintf(p, fmt, args);
-  va_end(args);
-  return res;
-}
-
-char *
-mp_vprintf_append(struct mempool *mp, char *ptr, const char *fmt, va_list args)
-{
-  size_t ofs = mp_open(mp, ptr);
-  ASSERT(ofs && !ptr[ofs - 1]);
-  return mp_vprintf_at(mp, ofs - 1, fmt, args);
-}
-
-char *
-mp_printf_append(struct mempool *mp, char *ptr, const char *fmt, ...)
-{
-  va_list args;
-  va_start(args, fmt);
-  char *res = mp_vprintf_append(mp, ptr, fmt, args);
-  va_end(args);
-  return res;
-}
-
-#ifdef TEST
-
-int main(void)
-{
-  struct mempool *mp = mp_new(64);
-  char *x = mp_printf(mp, "<Hello, %s!>", "World");
-  fputs(x, stdout);
-  x = mp_printf_append(mp, x, "<Appended>");
-  fputs(x, stdout);
-  x = mp_printf(mp, "<Hello, %50s!>\n", "World");
-  fputs(x, stdout);
-  return 0;
-}
-
-#endif
index 129b7336ac789aa42eb784f6fc542807284ae09b..dfc392edc5d32da84b619c1a2ba995a61175d13c 100644 (file)
@@ -1,8 +1,9 @@
 /*
  *     UCW Library -- Memory Pools (One-Time Allocation)
  *
- *     (c) 1997--2014 Martin Mares <mj@ucw.cz>
- *     (c) 2007--2015 Pavel Charvat <pchar@ucw.cz>
+ *     (c) 1997--2001 Martin Mares <mj@ucw.cz>
+ *     (c) 2007 Pavel Charvat <pchar@ucw.cz>
+ *     (c) 2015, 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
 
 #undef LOCAL_DEBUG
 
-#include <ucw/config.h>
-#include <ucw/lib.h>
-#include <ucw/alloc.h>
-#include <ucw/mempool.h>
-
 #include <string.h>
+#include <strings.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "contrib/asan.h"
+#include "contrib/macros.h"
+#include "contrib/ucw/mempool.h"
 
-/* FIXME: migrate to Knot DNS version of mempools. */
-#pragma GCC diagnostic ignored "-Wpointer-arith"
-
+/** Align an integer \p s to the nearest higher multiple of \p a (which should be a power of two) **/
+#define ALIGN_TO(s, a) (((s)+a-1)&~(a-1))
 #define MP_CHUNK_TAIL ALIGN_TO(sizeof(struct mempool_chunk), CPU_STRUCT_ALIGN)
-#define MP_SIZE_MAX (SIZE_MAX - MP_CHUNK_TAIL - CPU_PAGE_SIZE)
-
-struct mempool_chunk {
-#ifdef CONFIG_DEBUG
-  struct mempool *pool;                // Can be useful when analysing coredump for memory leaks
-#endif
-  struct mempool_chunk *next;
-  size_t size;
-};
+#define MP_SIZE_MAX (~0U - MP_CHUNK_TAIL - CPU_PAGE_SIZE)
+#define DBG(s, ...)
 
-static size_t
-mp_align_size(size_t size)
-{
+/** \note Imported MMAP backend from bigalloc.c */
+#define CONFIG_UCW_POOL_IS_MMAP
 #ifdef CONFIG_UCW_POOL_IS_MMAP
-  size = MAX(size, 64 + MP_CHUNK_TAIL);
-  return ALIGN_TO(size, CPU_PAGE_SIZE) - MP_CHUNK_TAIL;
-#else
-  return ALIGN_TO(size, CPU_STRUCT_ALIGN);
-#endif
-}
-
-static void *mp_allocator_alloc(struct ucw_allocator *a, size_t size)
+#include <sys/mman.h>
+static void *
+page_alloc(uint64_t len)
 {
-  struct mempool *mp = (struct mempool *) a;
-  return mp_alloc_fast(mp, size);
+       if (!len) {
+               return NULL;
+       }
+       if (len > SIZE_MAX) {
+               return NULL;
+       }
+       assert(!(len & (CPU_PAGE_SIZE-1)));
+       uint8_t *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+       if (p == (uint8_t*) MAP_FAILED) {
+               return NULL;
+       }
+       return p;
 }
 
-static void *mp_allocator_realloc(struct ucw_allocator *a, void *ptr, size_t old_size, size_t new_size)
+static void
+page_free(void *start, uint64_t len)
 {
-  if (new_size <= old_size)
-    return ptr;
-
-  /*
-   *  In the future, we might want to do something like mp_realloc(),
-   *  but we have to check that it is indeed the last block in the pool.
-   */
-  struct mempool *mp = (struct mempool *) a;
-  void *new = mp_alloc_fast(mp, new_size);
-  memcpy(new, ptr, old_size);
-  return new;
+       assert(!(len & (CPU_PAGE_SIZE-1)));
+       assert(!((uintptr_t) start & (CPU_PAGE_SIZE-1)));
+       munmap(start, len);
 }
+#endif
+
+struct mempool_chunk {
+       struct mempool_chunk *next;
+       unsigned size;
+};
 
-static void mp_allocator_free(struct ucw_allocator *a UNUSED, void *ptr UNUSED)
+static unsigned
+mp_align_size(unsigned size)
 {
-  // Does nothing
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+       return ALIGN_TO(size + MP_CHUNK_TAIL, CPU_PAGE_SIZE) - MP_CHUNK_TAIL;
+#else
+       return ALIGN_TO(size, CPU_STRUCT_ALIGN);
+#endif
 }
 
 void
-mp_init(struct mempool *pool, size_t chunk_size)
+mp_init(struct mempool *pool, unsigned chunk_size)
 {
-  chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
-  *pool = (struct mempool) {
-    .allocator = {
-      .alloc = mp_allocator_alloc,
-      .realloc = mp_allocator_realloc,
-      .free = mp_allocator_free,
-    },
-    .chunk_size = chunk_size,
-    .threshold = chunk_size >> 1,
-    .last_big = &pool->last_big
-  };
+       chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+       *pool = (struct mempool) {
+               .chunk_size = chunk_size,
+               .threshold = chunk_size >> 1,
+               .last_big = &pool->last_big
+       };
 }
 
 static void *
-mp_new_big_chunk(struct mempool *pool, size_t size)
+mp_new_big_chunk(unsigned size)
 {
-  struct mempool_chunk *chunk;
-  chunk = malloc(size + MP_CHUNK_TAIL);
-  if (!chunk)
-    return NULL;
-  chunk = (struct mempool_chunk *)((char *)chunk + size);
-  chunk->size = size;
-  if (pool)
-    pool->total_size += size + MP_CHUNK_TAIL;
-  return chunk;
+       uint8_t *data = malloc(size + MP_CHUNK_TAIL);
+       if (!data) {
+               return NULL;
+       }
+       ASAN_POISON_MEMORY_REGION(data, size);
+       struct mempool_chunk *chunk = (struct mempool_chunk *)(data + size);
+       chunk->size = size;
+       return chunk;
 }
 
 static void
-mp_free_big_chunk(struct mempool *pool, struct mempool_chunk *chunk)
+mp_free_big_chunk(struct mempool_chunk *chunk)
 {
-  pool->total_size -= chunk->size + MP_CHUNK_TAIL;
-  free((void *)chunk - chunk->size);
+       void *ptr = (uint8_t *)chunk - chunk->size;
+       ASAN_UNPOISON_MEMORY_REGION(ptr, chunk->size);
+       free(ptr);
 }
 
 static void *
-mp_new_chunk(struct mempool *pool, size_t size)
+mp_new_chunk(unsigned size)
 {
 #ifdef CONFIG_UCW_POOL_IS_MMAP
-  struct mempool_chunk *chunk;
-  chunk = page_alloc(size + MP_CHUNK_TAIL) + size;
-  chunk->size = size;
-  if (pool)
-    pool->total_size += size + MP_CHUNK_TAIL;
-  return chunk;
+       uint8_t *data = page_alloc(size + MP_CHUNK_TAIL);
+       if (!data) {
+               return NULL;
+       }
+       ASAN_POISON_MEMORY_REGION(data, size);
+       struct mempool_chunk *chunk = (struct mempool_chunk *)(data + size);
+       chunk->size = size;
+       return chunk;
 #else
-  return mp_new_big_chunk(pool, size);
+       return mp_new_big_chunk(size);
 #endif
 }
 
 static void
-mp_free_chunk(struct mempool *pool, struct mempool_chunk *chunk)
+mp_free_chunk(struct mempool_chunk *chunk)
 {
 #ifdef CONFIG_UCW_POOL_IS_MMAP
-  pool->total_size -= chunk->size + MP_CHUNK_TAIL;
-  page_free((void *)chunk - chunk->size, chunk->size + MP_CHUNK_TAIL);
+       uint8_t *data = (uint8_t *)chunk - chunk->size;
+       ASAN_UNPOISON_MEMORY_REGION(data, chunk->size);
+       page_free(data, chunk->size + MP_CHUNK_TAIL);
 #else
-  mp_free_big_chunk(pool, chunk);
+       mp_free_big_chunk(chunk);
 #endif
 }
 
 struct mempool *
-mp_new(size_t chunk_size)
-{
-  chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
-  struct mempool_chunk *chunk = mp_new_chunk(NULL, chunk_size);
-  struct mempool *pool = (void *)chunk - chunk_size;
-  DBG("Creating mempool %p with %u bytes long chunks", pool, chunk_size);
-  chunk->next = NULL;
-#ifdef CONFIG_DEBUG
-  chunk->pool = pool;
-#endif
-  *pool = (struct mempool) {
-    .allocator = {
-      .alloc = mp_allocator_alloc,
-      .realloc = mp_allocator_realloc,
-      .free = mp_allocator_free,
-    },
-    .state = { .free = { chunk_size - sizeof(*pool) }, .last = { chunk } },
-    .chunk_size = chunk_size,
-    .threshold = chunk_size >> 1,
-    .last_big = &pool->last_big,
-    .total_size = chunk->size + MP_CHUNK_TAIL,
-  };
-  return pool;
+mp_new(unsigned chunk_size)
+{
+       chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+       struct mempool_chunk *chunk = mp_new_chunk(chunk_size);
+       struct mempool *pool = (void *)((char *)chunk - chunk_size);
+       ASAN_UNPOISON_MEMORY_REGION(pool, sizeof(*pool));
+       DBG("Creating mempool %p with %u bytes long chunks", pool, chunk_size);
+       chunk->next = NULL;
+       ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+       *pool = (struct mempool) {
+               .state = { .free = { chunk_size - sizeof(*pool) }, .last = { chunk } },
+               .chunk_size = chunk_size,
+               .threshold = chunk_size >> 1,
+               .last_big = &pool->last_big
+       };
+       return pool;
 }
 
 static void
-mp_free_chain(struct mempool *pool, struct mempool_chunk *chunk)
+mp_free_chain(struct mempool_chunk *chunk)
 {
-  while (chunk)
-    {
-      struct mempool_chunk *next = chunk->next;
-      mp_free_chunk(pool, chunk);
-      chunk = next;
-    }
+       while (chunk) {
+               ASAN_UNPOISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               struct mempool_chunk *next = chunk->next;
+               mp_free_chunk(chunk);
+               chunk = next;
+       }
 }
 
 static void
-mp_free_big_chain(struct mempool *pool, struct mempool_chunk *chunk)
+mp_free_big_chain(struct mempool_chunk *chunk)
 {
-  while (chunk)
-    {
-      struct mempool_chunk *next = chunk->next;
-      mp_free_big_chunk(pool, chunk);
-      chunk = next;
-    }
+       while (chunk) {
+               ASAN_UNPOISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               struct mempool_chunk *next = chunk->next;
+               mp_free_big_chunk(chunk);
+               chunk = next;
+       }
 }
 
 void
 mp_delete(struct mempool *pool)
 {
-  DBG("Deleting mempool %p", pool);
-  mp_free_big_chain(pool, pool->state.last[1]);
-  mp_free_chain(pool, pool->unused);
-  mp_free_chain(pool, pool->state.last[0]); // can contain the mempool structure
+       if (pool == NULL) {
+               return;
+       }
+       DBG("Deleting mempool %p", pool);
+       mp_free_big_chain(pool->state.last[1]);
+       mp_free_chain(pool->unused);
+       mp_free_chain(pool->state.last[0]); // can contain the mempool structure
 }
 
 void
 mp_flush(struct mempool *pool)
 {
-  mp_free_big_chain(pool, pool->state.last[1]);
-  struct mempool_chunk *chunk, *next;
-  for (chunk = pool->state.last[0]; chunk && (void *)chunk - chunk->size != pool; chunk = next)
-    {
-      next = chunk->next;
-      chunk->next = pool->unused;
-      pool->unused = chunk;
-    }
-  pool->state.last[0] = chunk;
-  pool->state.free[0] = chunk ? chunk->size - sizeof(*pool) : 0;
-  pool->state.last[1] = NULL;
-  pool->state.free[1] = 0;
-  pool->state.next = NULL;
-  pool->last_big = &pool->last_big;
+       mp_free_big_chain(pool->state.last[1]);
+       struct mempool_chunk *chunk = pool->state.last[0], *next;
+       while (chunk) {
+               ASAN_UNPOISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               if ((uint8_t *)chunk - chunk->size == (uint8_t *)pool) {
+                       break;
+               }
+               next = chunk->next;
+               chunk->next = pool->unused;
+               ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               pool->unused = chunk;
+               chunk = next;
+       }
+       pool->state.last[0] = chunk;
+       if (chunk) {
+               pool->state.free[0] = chunk->size - sizeof(*pool);
+               ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+       } else {
+               pool->state.free[0] = 0;
+       }
+       pool->state.last[1] = NULL;
+       pool->state.free[1] = 0;
+       pool->last_big = &pool->last_big;
 }
 
 static void
-mp_stats_chain(struct mempool *pool, struct mempool_chunk *chunk, struct mempool_stats *stats, uint idx)
-{
-  while (chunk)
-    {
-      stats->chain_size[idx] += chunk->size + MP_CHUNK_TAIL;
-      stats->chain_count[idx]++;
-      if (idx < 2)
-       {
-         stats->used_size += chunk->size;
-         if ((byte *)pool == (byte *)chunk - chunk->size)
-           stats->used_size -= sizeof(*pool);
+mp_stats_chain(struct mempool_chunk *chunk, struct mempool_stats *stats, unsigned idx)
+{
+       struct mempool_chunk *next;
+       while (chunk) {
+               ASAN_UNPOISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               stats->chain_size[idx] += chunk->size + sizeof(*chunk);
+               stats->chain_count[idx]++;
+               next = chunk->next;
+               ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               chunk = next;
        }
-      chunk = chunk->next;
-    }
-  stats->total_size += stats->chain_size[idx];
+       stats->total_size += stats->chain_size[idx];
 }
 
 void
 mp_stats(struct mempool *pool, struct mempool_stats *stats)
 {
-  bzero(stats, sizeof(*stats));
-  mp_stats_chain(pool, pool->state.last[0], stats, 0);
-  mp_stats_chain(pool, pool->state.last[1], stats, 1);
-  mp_stats_chain(pool, pool->unused, stats, 2);
-  stats->used_size -= pool->state.free[0] + pool->state.free[1];
-  ASSERT(stats->total_size == pool->total_size);
-  ASSERT(stats->used_size <= stats->total_size);
+       bzero(stats, sizeof(*stats));
+       mp_stats_chain(pool->state.last[0], stats, 0);
+       mp_stats_chain(pool->state.last[1], stats, 1);
+       mp_stats_chain(pool->unused, stats, 2);
 }
 
-u64
+uint64_t
 mp_total_size(struct mempool *pool)
 {
-  return pool->total_size;
-}
-
-void
-mp_shrink(struct mempool *pool, u64 min_total_size)
-{
-  while (1)
-    {
-      struct mempool_chunk *chunk = pool->unused;
-      if (!chunk || pool->total_size - (chunk->size + MP_CHUNK_TAIL) < min_total_size)
-       break;
-      pool->unused = chunk->next;
-      mp_free_chunk(pool, chunk);
-    }
+       struct mempool_stats stats;
+       mp_stats(pool, &stats);
+       return stats.total_size;
 }
 
-void *
-mp_alloc_internal(struct mempool *pool, size_t size)
-{
-  struct mempool_chunk *chunk;
-  if (size <= pool->threshold)
-    {
-      pool->idx = 0;
-      if (pool->unused)
-        {
-         chunk = pool->unused;
-         pool->unused = chunk->next;
-       }
-      else
-       {
-         chunk = mp_new_chunk(pool, pool->chunk_size);
-#ifdef CONFIG_DEBUG
-         chunk->pool = pool;
-#endif
+static void *
+mp_alloc_internal(struct mempool *pool, unsigned size)
+{
+       struct mempool_chunk *chunk;
+       if (size <= pool->threshold) {
+               pool->idx = 0;
+               if (pool->unused) {
+                       chunk = pool->unused;
+                       ASAN_UNPOISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+                       pool->unused = chunk->next;
+               } else {
+                       chunk = mp_new_chunk(pool->chunk_size);
+               }
+               chunk->next = pool->state.last[0];
+               ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               pool->state.last[0] = chunk;
+               pool->state.free[0] = pool->chunk_size - size;
+               return (uint8_t *)chunk - pool->chunk_size;
+       } else if (size <= MP_SIZE_MAX) {
+               pool->idx = 1;
+               unsigned aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN);
+               chunk = mp_new_big_chunk(aligned);
+               if (!chunk) {
+                       return NULL;
+               }
+               chunk->next = pool->state.last[1];
+               ASAN_POISON_MEMORY_REGION(chunk, sizeof(struct mempool_chunk));
+               pool->state.last[1] = chunk;
+               pool->state.free[1] = aligned - size;
+               return pool->last_big = (uint8_t *)chunk - aligned;
+       } else {
+               fprintf(stderr, "Cannot allocate %u bytes from a mempool", size);
+               assert(0);
+               return NULL;
        }
-      chunk->next = pool->state.last[0];
-      pool->state.last[0] = chunk;
-      pool->state.free[0] = pool->chunk_size - size;
-      return (void *)chunk - pool->chunk_size;
-    }
-  else if (likely(size <= MP_SIZE_MAX))
-    {
-      pool->idx = 1;
-      size_t aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN);
-      chunk = mp_new_big_chunk(pool, aligned);
-      chunk->next = pool->state.last[1];
-#ifdef CONFIG_DEBUG
-      chunk->pool = pool;
-#endif
-      pool->state.last[1] = chunk;
-      pool->state.free[1] = aligned - size;
-      return pool->last_big = (void *)chunk - aligned;
-    }
-  else
-    return NULL;
-}
-
-void *
-mp_alloc(struct mempool *pool, size_t size)
-{
-  return mp_alloc_fast(pool, size);
-}
-
-void *
-mp_alloc_noalign(struct mempool *pool, size_t size)
-{
-  return mp_alloc_fast_noalign(pool, size);
-}
-
-void *
-mp_alloc_zero(struct mempool *pool, size_t size)
-{
-  void *ptr = mp_alloc_fast(pool, size);
-  bzero(ptr, size);
-  return ptr;
-}
-
-void *
-mp_start_internal(struct mempool *pool, size_t size)
-{
-  void *ptr = mp_alloc_internal(pool, size);
-  if (!ptr)
-    return NULL;
-  pool->state.free[pool->idx] += size;
-  return ptr;
 }
 
 void *
-mp_start(struct mempool *pool, size_t size)
-{
-  return mp_start_fast(pool, size);
-}
-
-void *
-mp_start_noalign(struct mempool *pool, size_t size)
-{
-  return mp_start_fast_noalign(pool, size);
-}
-
-void *
-mp_grow_internal(struct mempool *pool, size_t size)
-{
-  if (unlikely(size > MP_SIZE_MAX))
-    return NULL;
-  size_t avail = mp_avail(pool);
-  void *ptr = mp_ptr(pool);
-  if (pool->idx)
-    {
-      size_t amortized = likely(avail <= MP_SIZE_MAX / 2) ? avail * 2 : MP_SIZE_MAX;
-      amortized = MAX(amortized, size);
-      amortized = ALIGN_TO(amortized, CPU_STRUCT_ALIGN);
-      struct mempool_chunk *chunk = pool->state.last[1], *next = chunk->next;
-      pool->total_size = pool->total_size - chunk->size + amortized;
-      void *nptr = realloc(ptr, amortized + MP_CHUNK_TAIL);
-      if (!nptr)
-        return NULL;
-      ptr = nptr;
-      chunk = ptr + amortized;
-      chunk->next = next;
-      chunk->size = amortized;
-      pool->state.last[1] = chunk;
-      pool->state.free[1] = amortized;
-      pool->last_big = ptr;
-      return ptr;
-    }
-  else
-    {
-      void *p = mp_start_internal(pool, size);
-      memcpy(p, ptr, avail);
-      return p;
-    }
-}
-
-size_t
-mp_open(struct mempool *pool, void *ptr)
-{
-  return mp_open_fast(pool, ptr);
-}
-
-void *
-mp_realloc(struct mempool *pool, void *ptr, size_t size)
-{
-  return mp_realloc_fast(pool, ptr, size);
+mp_alloc(struct mempool *pool, unsigned size)
+{
+       unsigned avail = pool->state.free[0] & ~(CPU_STRUCT_ALIGN - 1);
+       void *ptr = NULL;
+       if (size <= avail) {
+               pool->state.free[0] = avail - size;
+               ptr = (uint8_t*)pool->state.last[0] - avail;
+       } else {
+               ptr = mp_alloc_internal(pool, size);
+       }
+       ASAN_UNPOISON_MEMORY_REGION(ptr, size);
+       return ptr;
 }
 
 void *
-mp_realloc_zero(struct mempool *pool, void *ptr, size_t size)
-{
-  size_t old_size = mp_open_fast(pool, ptr);
-  ptr = mp_grow(pool, size);
-  if (size > old_size)
-    bzero(ptr + old_size, size - old_size);
-  mp_end(pool, ptr + size);
-  return ptr;
+mp_alloc_noalign(struct mempool *pool, unsigned size)
+{
+       void *ptr = NULL;
+       if (size <= pool->state.free[0]) {
+               ptr = (uint8_t*)pool->state.last[0] - pool->state.free[0];
+               pool->state.free[0] -= size;
+       } else {
+               ptr = mp_alloc_internal(pool, size);
+       }
+       ASAN_UNPOISON_MEMORY_REGION(ptr, size);
+       return ptr;
 }
 
 void *
-mp_spread_internal(struct mempool *pool, void *p, size_t size)
-{
-  void *old = mp_ptr(pool);
-  void *new = mp_grow_internal(pool, p-old+size);
-  if (!new) {
-    return NULL;
-  }
-  return p-old+new;
-}
-
-void
-mp_restore(struct mempool *pool, struct mempool_state *state)
+mp_alloc_zero(struct mempool *pool, unsigned size)
 {
-  struct mempool_chunk *chunk, *next;
-  struct mempool_state s = *state;
-  for (chunk = pool->state.last[0]; chunk != s.last[0]; chunk = next)
-    {
-      next = chunk->next;
-      chunk->next = pool->unused;
-      pool->unused = chunk;
-    }
-  for (chunk = pool->state.last[1]; chunk != s.last[1]; chunk = next)
-    {
-      next = chunk->next;
-      mp_free_big_chunk(pool, chunk);
-    }
-  pool->state = s;
-  pool->last_big = &pool->last_big;
+       void *ptr = mp_alloc(pool, size);
+       bzero(ptr, size);
+       return ptr;
 }
-
-struct mempool_state *
-mp_push(struct mempool *pool)
-{
-  struct mempool_state state = pool->state;
-  struct mempool_state *p = mp_alloc_fast(pool, sizeof(*p));
-  *p = state;
-  pool->state.next = p;
-  return p;
-}
-
-void
-mp_pop(struct mempool *pool)
-{
-  ASSERT(pool->state.next);
-  mp_restore(pool, pool->state.next);
-}
-
-#ifdef TEST
-
-#include <ucw/getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-static void
-fill(byte *ptr, uint len, uint magic)
-{
-  while (len--)
-    *ptr++ = (magic++ & 255);
-}
-
-static void
-check(byte *ptr, uint len, uint magic, uint align)
-{
-  ASSERT(!((uintptr_t)ptr & (align - 1)));
-  while (len--)
-    if (*ptr++ != (magic++ & 255))
-      ASSERT(0);
-}
-
-int main(int argc, char **argv)
-{
-  srand(time(NULL));
-  log_init(argv[0]);
-  cf_def_file = NULL;
-  if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) >= 0 || argc != optind)
-    die("Invalid usage");
-
-  uint max = 1000, n = 0, m = 0, can_realloc = 0;
-  void *ptr[max];
-  struct mempool_state *state[max];
-  uint len[max], num[max], align[max];
-  struct mempool *mp = mp_new(128), mp_static;
-
-  for (uint i = 0; i < 5000; i++)
-    {
-      for (uint j = 0; j < n; j++)
-       check(ptr[j], len[j], j, align[j]);
-#if 0
-      DBG("free_small=%u free_big=%u idx=%u chunk_size=%u last_big=%p", mp->state.free[0], mp->state.free[1], mp->idx, mp->chunk_size, mp->last_big);
-      for (struct mempool_chunk *ch = mp->state.last[0]; ch; ch = ch->next)
-       DBG("small %p %p %p %d", (byte *)ch - ch->size, ch, ch + 1, ch->size);
-      for (struct mempool_chunk *ch = mp->state.last[1]; ch; ch = ch->next)
-       DBG("big %p %p %p %d", (byte *)ch - ch->size, ch, ch + 1, ch->size);
-#endif
-      int r = random_max(100);
-      if ((r -= 1) < 0)
-        {
-         DBG("flush");
-         mp_flush(mp);
-         n = m = 0;
-       }
-      else if ((r -= 1) < 0)
-        {
-         DBG("delete & new");
-         mp_delete(mp);
-         if (random_max(2))
-           mp = mp_new(random_max(0x1000) + 1);
-         else
-           mp = &mp_static, mp_init(mp, random_max(512) + 1);
-         n = m = 0;
-       }
-      else if (n < max && (r -= 30) < 0)
-        {
-         len[n] = random_max(0x2000);
-         DBG("alloc(%u)", len[n]);
-         align[n] = random_max(2) ? CPU_STRUCT_ALIGN : 1;
-         ptr[n] = (align[n] == 1) ? mp_alloc_fast_noalign(mp, len[n]) : mp_alloc_fast(mp, len[n]);
-         DBG(" -> (%p)", ptr[n]);
-         fill(ptr[n], len[n], n);
-         n++;
-         can_realloc = 1;
-       }
-      else if (n < max && (r -= 20) < 0)
-        {
-         len[n] = random_max(0x2000);
-         DBG("start(%u)", len[n]);
-         align[n] = random_max(2) ? CPU_STRUCT_ALIGN : 1;
-         ptr[n] = (align[n] == 1) ? mp_start_fast_noalign(mp, len[n]) : mp_start_fast(mp, len[n]);
-         DBG(" -> (%p)", ptr[n]);
-         fill(ptr[n], len[n], n);
-         n++;
-         can_realloc = 1;
-         goto grow;
-       }
-      else if (can_realloc && n && (r -= 10) < 0)
-        {
-         if (mp_open(mp, ptr[n - 1]) != len[n - 1])
-           ASSERT(0);
-grow:
-         {
-           uint k = n - 1;
-           for (uint i = random_max(4); i--; )
-             {
-               uint l = len[k];
-               len[k] = random_max(0x2000);
-               DBG("grow(%u)", len[k]);
-               ptr[k] = mp_grow(mp, len[k]);
-               DBG(" -> (%p)", ptr[k]);
-               check(ptr[k], MIN(l, len[k]), k, align[k]);
-               fill(ptr[k], len[k], k);
-             }
-           mp_end(mp, ptr[k] + len[k]);
-         }
-       }
-      else if (can_realloc && n && (r -= 20) < 0)
-        {
-         uint i = n - 1, l = len[i];
-         DBG("realloc(%p, %u)", ptr[i], len[i]);
-         ptr[i] = mp_realloc(mp, ptr[i], len[i] = random_max(0x2000));
-         DBG(" -> (%p, %u)", ptr[i], len[i]);
-         check(ptr[i],  MIN(len[i], l), i, align[i]);
-         fill(ptr[i], len[i], i);
-       }
-      else if (m < max && (r -= 5) < 0)
-        {
-         DBG("push(%u)", m);
-         num[m] = n;
-         state[m++] = mp_push(mp);
-         can_realloc = 0;
-       }
-      else if (m && (r -= 2) < 0)
-        {
-         m--;
-         DBG("pop(%u)", m);
-         mp_pop(mp);
-         n = num[m];
-         can_realloc = 0;
-       }
-      else if (m && (r -= 1) < 0)
-        {
-         uint i = random_max(m);
-         DBG("restore(%u)", i);
-         mp_restore(mp, state[i]);
-         n = num[m = i];
-         can_realloc = 0;
-       }
-      else if (can_realloc && n && (r -= 5) < 0)
-        ASSERT(mp_size(mp, ptr[n - 1]) == len[n - 1]);
-      else
-       {
-         struct mempool_stats stats;
-         mp_stats(mp, &stats);
-       }
-    }
-
-  mp_delete(mp);
-  return 0;
-}
-
-#endif
index aa621e346e9e421a5d735d9faab9f7c5126d3fdf..46dc9d7c6133d581a84fac1adb6ddfaa1e09e2bd 100644 (file)
@@ -1,55 +1,25 @@
 /*
  *     UCW Library -- Memory Pools
  *
- *     (c) 1997--2015 Martin Mares <mj@ucw.cz>
+ *     (c) 1997--2005 Martin Mares <mj@ucw.cz>
  *     (c) 2007 Pavel Charvat <pchar@ucw.cz>
+ *     (c) 2015, 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
  */
 
-#ifndef _UCW_POOLS_H
-#define _UCW_POOLS_H
+#pragma once
 
-#include "lib/defines.h"
-#include <ucw/alloc.h>
-#include <ucw/config.h>
-#include <ucw/lib.h>
 #include <string.h>
+#include <stdint.h>
+
+#include "lib/defines.h"
 
-#ifdef CONFIG_UCW_CLEAN_ABI
-#define mp_alloc ucw_mp_alloc
-#define mp_alloc_internal ucw_mp_alloc_internal
-#define mp_alloc_noalign ucw_mp_alloc_noalign
-#define mp_alloc_zero ucw_mp_alloc_zero
-#define mp_delete ucw_mp_delete
-#define mp_flush ucw_mp_flush
-#define mp_grow_internal ucw_mp_grow_internal
-#define mp_init ucw_mp_init
-#define mp_memdup ucw_mp_memdup
-#define mp_multicat ucw_mp_multicat
-#define mp_new ucw_mp_new
-#define mp_open ucw_mp_open
-#define mp_pop ucw_mp_pop
-#define mp_printf ucw_mp_printf
-#define mp_printf_append ucw_mp_printf_append
-#define mp_push ucw_mp_push
-#define mp_realloc ucw_mp_realloc
-#define mp_realloc_zero ucw_mp_realloc_zero
-#define mp_restore ucw_mp_restore
-#define mp_shrink ucw_mp_shrink
-#define mp_spread_internal ucw_mp_spread_internal
-#define mp_start ucw_mp_start
-#define mp_start_internal ucw_mp_start_internal
-#define mp_start_noalign ucw_mp_start_noalign
-#define mp_stats ucw_mp_stats
-#define mp_str_from_mem ucw_mp_str_from_mem
-#define mp_strdup ucw_mp_strdup
-#define mp_strjoin ucw_mp_strjoin
-#define mp_total_size ucw_mp_total_size
-#define mp_vprintf ucw_mp_vprintf
-#define mp_vprintf_append ucw_mp_vprintf_append
-#endif
+/** \todo This shouldn't be precalculated, but computed on load. */
+#define CPU_PAGE_SIZE 4096
+
+#define CPU_STRUCT_ALIGN (sizeof(void*))
 
 /***
  * [[defs]]
  ***/
 
 /**
- * Memory pool state (see @mp_push(), ...).
+ * Memory pool state (see mp_push(), ...).
  * You should use this one as an opaque handle only, the insides are internal.
  **/
 struct mempool_state {
-  size_t free[2];
-  void *last[2];
-  struct mempool_state *next;
+       unsigned free[2];
+       void *last[2];
 };
 
 /**
@@ -72,19 +41,15 @@ struct mempool_state {
  * You should use this one as an opaque handle only, the insides are internal.
  **/
 struct mempool {
-  struct ucw_allocator allocator;      // This must be the first element
-  struct mempool_state state;
-  void *unused, *last_big;
-  size_t chunk_size, threshold;
-  uint idx;
-  u64 total_size;
+       struct mempool_state state;
+       void *unused, *last_big;
+       unsigned chunk_size, threshold, idx;
 };
 
-struct mempool_stats {                 /** Mempool statistics. See @mp_stats(). **/
-  u64 total_size;                      /* Real allocated size in bytes */
-  u64 used_size;                       /* Estimated size allocated from mempool to application */
-  uint chain_count[3];                 /* Number of allocated chunks in small/big/unused chains */
-  u64 chain_size[3];                   /* Size of allocated chunks in small/big/unused chains */
+struct mempool_stats {                 /** Mempool statistics. See mp_stats(). **/
+       uint64_t total_size;            /** Real allocated size in bytes. */
+       unsigned chain_count[3];        /** Number of allocated chunks in small/big/unused chains. */
+       unsigned chain_size[3];         /** Size of allocated chunks in small/big/unused chains. */
 };
 
 /***
@@ -95,62 +60,45 @@ struct mempool_stats {                      /** Mempool statistics. See @mp_stats(). **/
 
 /**
  * Initialize a given mempool structure.
- * @chunk_size must be in the interval `[1, SIZE_MAX / 2]`.
+ * \p chunk_size must be in the interval `[1, UINT_MAX / 2]`.
  * It will allocate memory by this large chunks and take
  * memory to satisfy requests from them.
  *
  * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
  **/
-KR_EXPORT
-void mp_init(struct mempool *pool, size_t chunk_size);
+KR_EXPORT void mp_init(struct mempool *pool, unsigned chunk_size);
 
 /**
  * Allocate and initialize a new memory pool.
- * See @mp_init() for @chunk_size limitations.
+ * See \ref mp_init() for \p chunk_size limitations.
  *
  * The new mempool structure is allocated on the new mempool.
  *
  * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
  **/
-KR_EXPORT
-struct mempool *mp_new(size_t chunk_size);
+KR_EXPORT struct mempool *mp_new(unsigned chunk_size);
 
 /**
  * Cleanup mempool initialized by mp_init or mp_new.
  * Frees all the memory allocated by this mempool and,
- * if created by @mp_new(), the @pool itself.
+ * if created by \ref mp_new(), the \p pool itself.
  **/
-KR_EXPORT
-void mp_delete(struct mempool *pool);
+KR_EXPORT void mp_delete(struct mempool *pool);
 
 /**
  * Frees all data on a memory pool, but leaves it working.
  * It can keep some of the chunks allocated to serve
- * further allocation requests. Leaves the @pool alive,
- * even if it was created with @mp_new().
+ * further allocation requests. Leaves the \p pool alive,
+ * even if it was created with \ref mp_new().
  **/
-KR_EXPORT
-void mp_flush(struct mempool *pool);
+KR_EXPORT void mp_flush(struct mempool *pool);
 
 /**
  * Compute some statistics for debug purposes.
  * See the definition of the <<struct_mempool_stats,mempool_stats structure>>.
- * This function scans the chunk list, so it can be slow. If you are interested
- * in total memory consumption only, mp_total_size() is faster.
- **/
-void mp_stats(struct mempool *pool, struct mempool_stats *stats);
-
-/**
- * Return how many bytes were allocated by the pool, including unused parts
- * of chunks. This function runs in constant time.
- **/
-u64 mp_total_size(struct mempool *pool);
-
-/**
- * Release unused chunks of memory reserved for further allocation
- * requests, but stop if mp_total_size() would drop below @min_total_size.
  **/
-void mp_shrink(struct mempool *pool, u64 min_total_size);
+KR_EXPORT void mp_stats(struct mempool *pool, struct mempool_stats *stats);
+KR_EXPORT uint64_t mp_total_size(struct mempool *pool);        /** How many bytes were allocated by the pool. **/
 
 /***
  * [[alloc]]
@@ -158,12 +106,9 @@ void mp_shrink(struct mempool *pool, u64 min_total_size);
  * -------------------
  ***/
 
-/* For internal use only, do not call directly */
-void *mp_alloc_internal(struct mempool *pool, size_t size) LIKE_MALLOC;
-
 /**
- * The function allocates new @size bytes on a given memory pool.
- * If the @size is zero, the resulting pointer is undefined,
+ * The function allocates new \p size bytes on a given memory pool.
+ * If the \p size is zero, the resulting pointer is undefined,
  * but it may be safely reallocated or used as the parameter
  * to other functions below.
  *
@@ -171,403 +116,14 @@ void *mp_alloc_internal(struct mempool *pool, size_t size) LIKE_MALLOC;
  * `CPU_STRUCT_ALIGN` bytes and this condition remains true also
  * after future reallocations.
  **/
-KR_EXPORT
-void *mp_alloc(struct mempool *pool, size_t size);
-
-/**
- * The same as @mp_alloc(), but the result may be unaligned.
- **/
-void *mp_alloc_noalign(struct mempool *pool, size_t size);
-
-/**
- * The same as @mp_alloc(), but fills the newly allocated memory with zeroes.
- **/
-void *mp_alloc_zero(struct mempool *pool, size_t size);
-
-/**
- * Inlined version of @mp_alloc().
- **/
-static inline void *mp_alloc_fast(struct mempool *pool, size_t size)
-{
-  size_t avail = pool->state.free[0] & ~(size_t)(CPU_STRUCT_ALIGN - 1);
-  if (size <= avail)
-    {
-      pool->state.free[0] = avail - size;
-      return (byte *)pool->state.last[0] - avail;
-    }
-  else
-    return mp_alloc_internal(pool, size);
-}
-
-/**
- * Inlined version of @mp_alloc_noalign().
- **/
-static inline void *mp_alloc_fast_noalign(struct mempool *pool, size_t size)
-{
-  if (size <= pool->state.free[0])
-    {
-      void *ptr = (byte *)pool->state.last[0] - pool->state.free[0];
-      pool->state.free[0] -= size;
-      return ptr;
-    }
-  else
-    return mp_alloc_internal(pool, size);
-}
-
-/**
- * Return a generic allocator representing the given mempool.
- **/
-static inline struct ucw_allocator *mp_get_allocator(struct mempool *mp)
-{
-  return &mp->allocator;
-}
-
-/***
- * [[gbuf]]
- * Growing buffers
- * ---------------
- *
- * You do not need to know, how a buffer will need to be large,
- * you can grow it incrementally to needed size. You can grow only
- * one buffer at a time on a given mempool.
- *
- * Similar functionality is provided by <<growbuf:,growing buffes>> module.
- ***/
-
-/* For internal use only, do not call directly */
-void *mp_start_internal(struct mempool *pool, size_t size) LIKE_MALLOC;
-void *mp_grow_internal(struct mempool *pool, size_t size);
-void *mp_spread_internal(struct mempool *pool, void *p, size_t size);
-
-static inline uint mp_idx(struct mempool *pool, void *ptr)
-{
-  return ptr == pool->last_big;
-}
-
-/**
- * Open a new growing buffer (at least @size bytes long).
- * If the @size is zero, the resulting pointer is undefined,
- * but it may be safely reallocated or used as the parameter
- * to other functions below.
- *
- * The resulting pointer is always aligned to a multiple of
- * `CPU_STRUCT_ALIGN` bytes and this condition remains true also
- * after future reallocations. There is an unaligned version as well.
- *
- * Keep in mind that you can't make any other pool allocations
- * before you "close" the growing buffer with @mp_end().
- */
-void *mp_start(struct mempool *pool, size_t size);
-void *mp_start_noalign(struct mempool *pool, size_t size);
-
-/**
- * Inlined version of @mp_start().
- **/
-static inline void *mp_start_fast(struct mempool *pool, size_t size)
-{
-  size_t avail = pool->state.free[0] & ~(size_t)(CPU_STRUCT_ALIGN - 1);
-  if (size <= avail)
-    {
-      pool->idx = 0;
-      pool->state.free[0] = avail;
-      return (byte *)pool->state.last[0] - avail;
-    }
-  else
-    return mp_start_internal(pool, size);
-}
+KR_EXPORT void *mp_alloc(struct mempool *pool, unsigned size);
 
 /**
- * Inlined version of @mp_start_noalign().
+ * The same as \ref mp_alloc(), but the result may be unaligned.
  **/
-static inline void *mp_start_fast_noalign(struct mempool *pool, size_t size)
-{
-  if (size <= pool->state.free[0])
-    {
-      pool->idx = 0;
-      return (byte *)pool->state.last[0] - pool->state.free[0];
-    }
-  else
-    return mp_start_internal(pool, size);
-}
-
-/**
- * Return start pointer of the growing buffer allocated by latest @mp_start() or a similar function.
- **/
-static inline void *mp_ptr(struct mempool *pool)
-{
-  return (byte *)pool->state.last[pool->idx] - pool->state.free[pool->idx];
-}
-
-/**
- * Return the number of bytes available for extending the growing buffer.
- * (Before a reallocation will be needed).
- **/
-static inline size_t mp_avail(struct mempool *pool)
-{
-  return pool->state.free[pool->idx];
-}
-
-/**
- * Grow the buffer allocated by @mp_start() to be at least @size bytes long
- * (@size may be less than @mp_avail(), even zero). Reallocated buffer may
- * change its starting position. The content will be unchanged to the minimum
- * of the old and new sizes; newly allocated memory will be uninitialized.
- * Multiple calls to mp_grow() have amortized linear cost wrt. the maximum value of @size. */
-static inline void *mp_grow(struct mempool *pool, size_t size)
-{
-  return (size <= mp_avail(pool)) ? mp_ptr(pool) : mp_grow_internal(pool, size);
-}
+KR_EXPORT void *mp_alloc_noalign(struct mempool *pool, unsigned size);
 
 /**
- * Grow the buffer by at least one byte -- equivalent to <<mp_grow(),`mp_grow`>>`(@pool, @mp_avail(pool) + 1)`.
+ * The same as \ref mp_alloc(), but fills the newly allocated memory with zeroes.
  **/
-static inline void *mp_expand(struct mempool *pool)
-{
-  return mp_grow_internal(pool, mp_avail(pool) + 1);
-}
-
-/**
- * Ensure that there is at least @size bytes free after @p,
- * if not, reallocate and adjust @p.
- **/
-static inline void *mp_spread(struct mempool *pool, void *p, size_t size)
-{
-  return (((size_t)((byte *)pool->state.last[pool->idx] - (byte *)p) >= size) ? p : mp_spread_internal(pool, p, size));
-}
-
-/**
- * Append a character to the growing buffer. Called with @p pointing after
- * the last byte in the buffer, returns a pointer after the last byte
- * of the new (possibly reallocated) buffer.
- **/
-static inline char *mp_append_char(struct mempool *pool, char *p, uint c)
-{
-  p = mp_spread(pool, p, 1);
-  *p++ = c;
-  return p;
-}
-
-/**
- * Append a memory block to the growing buffer. Called with @p pointing after
- * the last byte in the buffer, returns a pointer after the last byte
- * of the new (possibly reallocated) buffer.
- **/
-static inline void *mp_append_block(struct mempool *pool, void *p, const void *block, size_t size)
-{
-  char *q = mp_spread(pool, p, size);
-  memcpy(q, block, size);
-  return q + size;
-}
-
-/**
- * Append a string to the growing buffer. Called with @p pointing after
- * the last byte in the buffer, returns a pointer after the last byte
- * of the new (possibly reallocated) buffer.
- **/
-static inline void *mp_append_string(struct mempool *pool, void *p, const char *str)
-{
-  return mp_append_block(pool, p, str, strlen(str));
-}
-
-/**
- * Close the growing buffer. The @end must point just behind the data, you want to keep
- * allocated (so it can be in the interval `[@mp_ptr(@pool), @mp_ptr(@pool) + @mp_avail(@pool)]`).
- * Returns a pointer to the beginning of the just closed block.
- **/
-static inline void *mp_end(struct mempool *pool, void *end)
-{
-  void *p = mp_ptr(pool);
-  pool->state.free[pool->idx] = (byte *)pool->state.last[pool->idx] - (byte *)end;
-  return p;
-}
-
-/**
- * Close the growing buffer as a string. That is, append a zero byte and call mp_end().
- **/
-static inline char *mp_end_string(struct mempool *pool, void *end)
-{
-  end = mp_append_char(pool, end, 0);
-  return mp_end(pool, end);
-}
-
-/**
- * Return size in bytes of the last allocated memory block (with @mp_alloc() or @mp_end()).
- **/
-static inline size_t mp_size(struct mempool *pool, void *ptr)
-{
-  uint idx = mp_idx(pool, ptr);
-  return ((byte *)pool->state.last[idx] - (byte *)ptr) - pool->state.free[idx];
-}
-
-/**
- * Open the last memory block (allocated with @mp_alloc() or @mp_end())
- * for growing and return its size in bytes. The contents and the start pointer
- * remain unchanged. Do not forget to call @mp_end() to close it.
- **/
-size_t mp_open(struct mempool *pool, void *ptr);
-
-/**
- * Inlined version of @mp_open().
- **/
-static inline size_t mp_open_fast(struct mempool *pool, void *ptr)
-{
-  pool->idx = mp_idx(pool, ptr);
-  size_t size = ((byte *)pool->state.last[pool->idx] - (byte *)ptr) - pool->state.free[pool->idx];
-  pool->state.free[pool->idx] += size;
-  return size;
-}
-
-/**
- * Reallocate the last memory block (allocated with @mp_alloc() or @mp_end())
- * to the new @size. Behavior is similar to @mp_grow(), but the resulting
- * block is closed.
- **/
-void *mp_realloc(struct mempool *pool, void *ptr, size_t size);
-
-/**
- * The same as @mp_realloc(), but fills the additional bytes (if any) with zeroes.
- **/
-void *mp_realloc_zero(struct mempool *pool, void *ptr, size_t size);
-
-/**
- * Inlined version of @mp_realloc().
- **/
-static inline void *mp_realloc_fast(struct mempool *pool, void *ptr, size_t size)
-{
-  mp_open_fast(pool, ptr);
-  ptr = mp_grow(pool, size);
-  mp_end(pool, (byte *)ptr + size);
-  return ptr;
-}
-
-/***
- * [[store]]
- * Storing and restoring state
- * ---------------------------
- *
- * Mempools can remember history of what was allocated and return back
- * in time.
- ***/
-
-/**
- * Save the current state of a memory pool.
- * Do not call this function with an opened growing buffer.
- **/
-static inline void mp_save(struct mempool *pool, struct mempool_state *state)
-{
-  *state = pool->state;
-  pool->state.next = state;
-}
-
-/**
- * Save the current state to a newly allocated mempool_state structure.
- * Do not call this function with an opened growing buffer.
- **/
-struct mempool_state *mp_push(struct mempool *pool);
-
-/**
- * Restore the state saved by @mp_save() or @mp_push() and free all
- * data allocated after that point (including the state structure itself).
- * You can't reallocate the last memory block from the saved state.
- **/
-void mp_restore(struct mempool *pool, struct mempool_state *state);
-
-/**
- * Inlined version of @mp_restore().
- **/
-static inline void mp_restore_fast(struct mempool *pool, struct mempool_state *state)
-{
-  if (pool->state.last[0] != state->last[0] || pool->state.last[1] != state->last[1])
-    mp_restore(pool, state);
-  else
-    {
-      pool->state = *state;
-      pool->last_big = &pool->last_big;
-    }
-}
-
-/**
- * Restore the state saved by the last call to @mp_push().
- * @mp_pop() and @mp_push() works as a stack so you can push more states safely.
- **/
-void mp_pop(struct mempool *pool);
-
-
-/***
- * [[string]]
- * String operations
- * -----------------
- ***/
-
-char *mp_strdup(struct mempool *, const char *) LIKE_MALLOC;           /** Makes a copy of a string on a mempool. Returns NULL for NULL string. **/
-void *mp_memdup(struct mempool *, const void *, size_t) LIKE_MALLOC;   /** Makes a copy of a memory block on a mempool. **/
-/**
- * Concatenates all passed strings. The last parameter must be NULL.
- * This will concatenate two strings:
- *
- *   char *message = mp_multicat(pool, "hello ", "world", NULL);
- **/
-char *mp_multicat(struct mempool *, ...) LIKE_MALLOC SENTINEL_CHECK;
-/**
- * Concatenates two strings and stores result on @mp.
- */
-static inline char *LIKE_MALLOC mp_strcat(struct mempool *mp, const char *x, const char *y)
-{
-  return mp_multicat(mp, x, y, NULL);
-}
-/**
- * Join strings and place @sep between each two neighboring.
- * @p is the mempool to provide memory, @a is array of strings and @n
- * tells how many there is of them.
- **/
-char *mp_strjoin(struct mempool *p, char **a, uint n, uint sep) LIKE_MALLOC;
-/**
- * Convert memory block to a string. Makes a copy of the given memory block
- * in the mempool @p, adding an extra terminating zero byte at the end.
- **/
-char *mp_str_from_mem(struct mempool *p, const void *mem, size_t len) LIKE_MALLOC;
-
-
-/***
- * [[format]]
- * Formatted output
- * ---------------
- ***/
-
-/**
- * printf() into a in-memory string, allocated on the memory pool.
- **/
-KR_EXPORT
-char *mp_printf(struct mempool *mp, const char *fmt, ...) FORMAT_CHECK(printf,2,3) LIKE_MALLOC;
-/**
- * Like @mp_printf(), but uses `va_list` for parameters.
- **/
-char *mp_vprintf(struct mempool *mp, const char *fmt, va_list args) LIKE_MALLOC;
-/**
- * Like @mp_printf(), but it appends the data at the end of string
- * pointed to by @ptr. The string is @mp_open()ed, so you have to
- * provide something that can be.
- *
- * Returns pointer to the beginning of the string (the pointer may have
- * changed due to reallocation).
- *
- * In some versions of LibUCW, this function was called mp_append_printf(). However,
- * this name turned out to be confusing -- unlike other appending functions, this one is
- * not called on an opened growing buffer. The old name will be preserved for backward
- * compatibility for the time being.
- **/
-KR_EXPORT
-char *mp_printf_append(struct mempool *mp, char *ptr, const char *fmt, ...) FORMAT_CHECK(printf,3,4);
-#define mp_append_printf mp_printf_append
-/**
- * Like @mp_printf_append(), but uses `va_list` for parameters.
- *
- * In some versions of LibUCW, this function was called mp_append_vprintf(). However,
- * this name turned out to be confusing -- unlike other appending functions, this one is
- * not called on an opened growing buffer. The old name will be preserved for backward
- * compatibility for the time being.
- **/
-char *mp_vprintf_append(struct mempool *mp, char *ptr, const char *fmt, va_list args);
-#define mp_append_vprintf mp_vprintf_append
-
-#endif
+KR_EXPORT void *mp_alloc_zero(struct mempool *pool, unsigned size);
index 7c406bea429ad4b48f07c367574b41c5044265c2..9056528c9eddbabbf9b6ed0199d5440971c8acb3 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <string.h>
 #include <libknot/errcode.h>
-#include <contrib/ucw/lib.h>
 #include <contrib/ucw/mempool.h>
 #include <assert.h>
 
index c870d8cd48a217ae71ab9267cc0bdb07ccf3b689..a97af4e6eeff00229318578dd60594b75e5c957f 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <libknot/packet/pkt.h>
 
+#include "contrib/macros.h"
 #include "lib/defines.h"
 #include "daemon/session.h"
 #include "daemon/engine.h"
@@ -698,16 +699,6 @@ size_t session_wirebuf_get_free_size(struct session *session)
        return session->wire_buf_size - session->wire_buf_end_idx;
 }
 
-void session_poison(struct session *session)
-{
-       kr_asan_poison(session, sizeof(*session));
-}
-
-void session_unpoison(struct session *session)
-{
-       kr_asan_unpoison(session, sizeof(*session));
-}
-
 int session_wirebuf_process(struct session *session)
 {
        int ret = 0;
index 7b261a4c19a1f15faf6578a9405ad421d4db92c0..ecf4f12e9a55ce2bcedd0cedcd3ed00228f831ff 100644 (file)
@@ -133,11 +133,6 @@ int session_wirebuf_process(struct session *session);
 ssize_t session_wirebuf_consume(struct session *session,
                                const uint8_t *data, ssize_t len);
 
-/** poison session structure with ASAN. */
-void session_poison(struct session *session);
-/** unpoison session structure with ASAN. */
-void session_unpoison(struct session *session);
-
 knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm);
 int session_discard_packet(struct session *session, const knot_pkt_t *pkt);
 
index f88267626ce863252ce7e0597998f5666e8c9025..a2b102234f32dbf035dfa8eeb995076a587725b5 100644 (file)
@@ -29,8 +29,8 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "contrib/ucw/lib.h"
 #include "contrib/base64.h"
+#include "contrib/macros.h"
 #include "daemon/io.h"
 #include "daemon/tls.h"
 #include "daemon/worker.h"
index 586f64d970f84371c04ea42517bbbaa139e16a9f..df26ae60cca253482e57c2f18238c70de6feb79b 100644 (file)
@@ -17,6 +17,7 @@
 #include "kresconfig.h"
 #include "daemon/udp_queue.h"
 
+#include "contrib/macros.h"
 #include "daemon/session.h"
 #include "daemon/worker.h"
 #include "lib/generic/array.h"
index 0cbbcc7c06740b70471a06457f48f4678e68d48a..23abe92fd19cf20b5c62423293fae2218a220d76 100644 (file)
@@ -22,7 +22,7 @@
 #include <lauxlib.h>
 #include <libknot/packet/pkt.h>
 #include <libknot/descriptor.h>
-#include <contrib/ucw/lib.h>
+#include <contrib/macros.h>
 #include <contrib/ucw/mempool.h>
 #include <contrib/wire.h>
 #if defined(__GLIBC__) && defined(_GNU_SOURCE)
@@ -197,30 +197,6 @@ static void ioreq_kill_pending(struct qr_task *task)
        task->pending_count = 0;
 }
 
-/** @cond This memory layout is internal to mempool.c, use only for debugging. */
-#if defined(__SANITIZE_ADDRESS__)
-struct mempool_chunk {
-  struct mempool_chunk *next;
-  size_t size;
-};
-static void mp_poison(struct mempool *mp, bool poison)
-{
-       if (!poison) { /* @note mempool is part of the first chunk, unpoison it first */
-               kr_asan_unpoison(mp, sizeof(*mp));
-       }
-       struct mempool_chunk *chunk = mp->state.last[0];
-       void *chunk_off = (uint8_t *)chunk - chunk->size;
-       if (poison) {
-               kr_asan_poison(chunk_off, chunk->size);
-       } else {
-               kr_asan_unpoison(chunk_off, chunk->size);
-       }
-}
-#else
-#define mp_poison(mp, enable)
-#endif
-/** @endcond */
-
 /** Get a mempool.  (Recycle if possible.)  */
 static inline struct mempool *pool_borrow(struct worker_ctx *worker)
 {
@@ -228,7 +204,6 @@ static inline struct mempool *pool_borrow(struct worker_ctx *worker)
        if (worker->pool_mp.len > 0) {
                mp = array_tail(worker->pool_mp);
                array_pop(worker->pool_mp);
-               mp_poison(mp, 0);
        } else { /* No mempool on the freelist, create new one */
                mp = mp_new (4 * CPU_PAGE_SIZE);
        }
@@ -241,7 +216,6 @@ static inline void pool_release(struct worker_ctx *worker, struct mempool *mp)
        if (worker->pool_mp.len < MP_FREELIST_SIZE) {
                mp_flush(mp);
                array_push(worker->pool_mp, mp);
-               mp_poison(mp, 1);
        } else {
                mp_delete(mp);
        }
@@ -2013,7 +1987,6 @@ static inline void reclaim_mp_freelist(mp_freelist_t *list)
 {
        for (unsigned i = 0; i < list->len; ++i) {
                struct mempool *e = list->at[i];
-               kr_asan_unpoison(e, sizeof(*e));
                mp_delete(e);
        }
        array_clear(*list);
index ece97b96d5f2f1c5e6d030186a76dda17bb4d394..adc3f319682b2219b95f6c6d97ded37fe7d3081c 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "contrib/base32hex.h"
 #include "contrib/cleanup.h"
-#include "contrib/ucw/lib.h"
+#include "contrib/macros.h"
 #include "lib/cache/api.h"
 #include "lib/cache/cdb_lmdb.h"
 #include "lib/defines.h"
index aa34eaa94f25cbdaee8a67590016aac243683169..029e100084cf4778fded8d63dc1080b2247399d6 100644 (file)
@@ -21,7 +21,6 @@
 #include <sys/time.h>
 #include "lib/cache/cdb_api.h"
 #include "lib/defines.h"
-#include "contrib/ucw/config.h" /*uint*/
 
 /** When knot_pkt is passed from cache without ->wire, this is the ->size. */
 static const size_t PKT_SIZE_NOWIRE = -1;
index 48129635826116104695e9455ec6b27d26f88f6d..7f330763d3fb8e4e99d8e1aa198daa0043613424 100644 (file)
@@ -25,7 +25,7 @@
 #include <lmdb.h>
 
 #include "contrib/cleanup.h"
-#include "contrib/ucw/lib.h"
+#include "contrib/macros.h"
 #include "lib/cache/cdb_lmdb.h"
 #include "lib/cache/cdb_api.h"
 #include "lib/cache/api.h"
index e2fc2689bf7e2b375d984a2661a1f5f5b6c52a69..3f1ea059050415310306200f172c73531f71c9e1 100644 (file)
@@ -20,6 +20,7 @@
  * The packet is stashed in entry_h::data as uint16_t length + full packet wire format.
  */
 
+#include "contrib/macros.h"
 #include "lib/utils.h"
 #include "lib/layer/iterate.h" /* kr_response_classify */
 #include "lib/cache/impl.h"
index 56836a60a85353345de338b2ce64fb20e112c8d3..e66a25d4fd1c5413729a85be2e826b9570e51deb 100644 (file)
@@ -19,6 +19,7 @@
  * Prototypes in ./impl.h
  */
 
+#include "contrib/macros.h"
 #include "lib/cache/impl.h"
 
 int pkt_renew(knot_pkt_t *pkt, const knot_dname_t *name, uint16_t type)
index 74b3d349d07c9011ee297446ea1c27ef3644bcd9..590639198740684a06398af86f384c60ea876d52 100644 (file)
@@ -18,6 +18,8 @@
  * Implementation of NSEC (1) handling.  Prototypes in ./impl.h
  */
 
+#include "contrib/macros.h"
+
 #include "lib/cache/impl.h"
 #include "lib/dnssec/nsec.h"
 #include "lib/layer/iterate.h"
index d2ae72a6d6570d7560a21ff5ba148266d09301cf..8f3e51b1b6e6fc5d56387cb293b2264152fd5479 100644 (file)
@@ -21,6 +21,7 @@
 #include "lib/cache/impl.h"
 
 #include "contrib/base32hex.h"
+#include "contrib/macros.h"
 #include "lib/dnssec/nsec.h"
 #include "lib/layer/iterate.h"
 
index 558a594abcf13770a34313fcbd1e482a1b07cdb0..ae710b6f4f079fe834f0a8fed650c2cef66d0158 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "lib/cache/impl.h"
 
+#include "contrib/macros.h"
 #include "lib/dnssec/ta.h"
 #include "lib/layer/iterate.h"
 
index 37750c59a15758e9d0e8e64a347ce0ffe3f2b852..81c4525d883eabb45207d49aad9552820e89ee9a 100644 (file)
@@ -86,19 +86,6 @@ static inline int KR_COLD kr_error(int x) {
 #  define __SANITIZE_ADDRESS__ 1
 # endif
 #endif
-#if defined(__SANITIZE_ADDRESS__)
-void __asan_poison_memory_region(void const volatile *addr, size_t size);
-void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
-#define kr_asan_poison(addr, size) __asan_poison_memory_region((addr), (size))
-#define kr_asan_unpoison(addr, size) __asan_unpoison_memory_region((addr), (size))
-#define kr_asan_custom_poison(fn, addr) fn ##_poison((addr))
-#define kr_asan_custom_unpoison(fn, addr) fn ##_unpoison((addr))
-#else
-#define kr_asan_poison(addr, size)
-#define kr_asan_unpoison(addr, size)
-#define kr_asan_custom_poison(fn, addr)
-#define kr_asan_custom_unpoison(fn, addr)
-#endif
 
 #if defined(__SANITIZE_ADDRESS__) && defined(_FORTIFY_SOURCE)
        #error "You can't use address sanitizer with _FORTIFY_SOURCE"
index b2d02f0a1d36d58e4f8332cb4f5f1ee193759420..f760681b6f04f9d00e791477797faa68b169afa0 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include "lib/generic/lru.h"
+#include "contrib/macros.h"
 #include "contrib/murmurhash3/murmurhash3.h"
 #include "contrib/ucw/mempool.h"
 
index 135419a9d1c65d637ef7e01777acf9170946837d..95d6b187c75ae312ddbb23d40c8b609ea944f3fd 100644 (file)
@@ -68,7 +68,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "contrib/ucw/lib.h"
 #include "lib/utils.h"
 #include "libknot/mm_ctx.h"
 
index 45657c7c52f8f619da412737e0f1a002d6a501a6..72c76d16a3ef6dac1cc6c415fabe80ca0353ea73 100644 (file)
@@ -14,6 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "contrib/macros.h"
 #include "lib/generic/queue.h"
 #include <string.h>
 
index 755e7594d43a98ea2f85a3038ce022f15b12ca9a..797fc640551658b2c0ee28bf0bfdac50d88abe3a 100644 (file)
@@ -66,7 +66,7 @@
 #pragma once
 
 #include "lib/defines.h"
-#include "contrib/ucw/lib.h"
+#include "contrib/macros.h"
 #include <assert.h>
 #include <stdbool.h>
 #include <stddef.h>
index 41e9acc1a6f340b5484b7ad1e71e790cf1bed440..737db567e3f6e9da3a1f8c8b09e1266c563fe08c 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "lib/generic/trie.h"
 #include "lib/utils.h"
-#include "contrib/ucw/lib.h"
+#include "contrib/macros.h"
 
 #if defined(__i386) || defined(__x86_64) || defined(_M_IX86) \
        || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN) \
index 069b34f0ee3d265f47545a11ecb5eb8980716bb2..c58099e108965c45f9449fcd6fc90916d363e597 100644 (file)
@@ -37,6 +37,7 @@
 #include <libknot/rrtype/rrsig.h>
 
 #include "kresconfig.h"
+#include "contrib/macros.h"
 #include "lib/layer/iterate.h"
 #include "lib/resolve.h"
 #include "lib/rplan.h"
index 77ef7b802b2ee3647e5eddc6713aa7f2ac40f385..0852ac40e551545c2a6682086f79a761c6f30064 100644 (file)
 
 #include <arpa/inet.h>
 
+#include "contrib/macros.h"
 #include "lib/nsrep.h"
 #include "lib/rplan.h"
 #include "lib/resolve.h"
 #include "lib/defines.h"
 #include "lib/generic/pack.h"
-#include "contrib/ucw/lib.h"
 
 /** Some built-in unfairness ... */
 #ifndef FAVOUR_IPV6
index 6ef20979a57661685eba46bbf7e14c52e428c3af..e0b6a97be6f44abd5793b8afa7130e001db5f49f 100644 (file)
@@ -24,6 +24,7 @@
 #include <libknot/descriptor.h>
 #include <ucw/mempool.h>
 #include "kresconfig.h"
+#include "contrib/macros.h"
 #include "lib/resolve.h"
 #include "lib/layer.h"
 #include "lib/rplan.h"
index 0725083ff67fc4ad516f0ff8a3d55647bc925fed..53186a647054def32a842f13becb4fced2b01d4a 100644 (file)
@@ -19,6 +19,7 @@
 #include "contrib/ccan/asprintf/asprintf.h"
 #include "contrib/cleanup.h"
 #include "contrib/ucw/mempool.h"
+#include "contrib/macros.h"
 #include "kresconfig.h"
 #include "lib/defines.h"
 #include "lib/generic/array.h"
@@ -838,7 +839,10 @@ static void flags_to_str(char *dst, const knot_pkt_t *pkt, size_t maxlen)
        dst[offset] = 0;
 }
 
-static char *print_section_opt(struct mempool *mp, char *endp, const knot_rrset_t *rr, const uint8_t rcode)
+/**
+ * Caller must free() strung returned in printp argument.
+ */
+static int print_section_opt(char *outstr, int outsize, const knot_rrset_t *rr, const uint8_t rcode)
 {
        uint8_t ercode = knot_edns_get_ext_rcode(rr);
        uint16_t ext_rcode_id = knot_edns_whole_rcode(ercode, rcode);
@@ -854,7 +858,7 @@ static char *print_section_opt(struct mempool *mp, char *endp, const knot_rrset_
                }
        }
 
-       return mp_printf_append(mp, endp,
+       return snprintf(outstr, outsize,
                ";; EDNS PSEUDOSECTION:\n;; "
                "Version: %u; flags: %s; UDP size: %u B; ext-rcode: %s\n\n",
                knot_edns_get_version(rr),
@@ -864,14 +868,12 @@ static char *print_section_opt(struct mempool *mp, char *endp, const knot_rrset_
 
 }
 
-char *kr_pkt_text(const knot_pkt_t *pkt)
+static int kr_pkt_text_internal(char *outstr, int outsize, const knot_pkt_t *pkt)
 {
        if (!pkt) {
-               return NULL;
+               return -1;
        }
 
-       struct mempool *mp = mp_new(512);
-
        static const char * snames[] = {
                ";; ANSWER SECTION", ";; AUTHORITY SECTION", ";; ADDITIONAL SECTION"
        };
@@ -884,6 +886,8 @@ char *kr_pkt_text(const knot_pkt_t *pkt)
        const knot_lookup_t *opcode = knot_lookup_by_id(knot_opcode_names, pkt_opcode);
        uint16_t qry_id = knot_wire_get_id(pkt->wire);
        uint16_t qdcount = knot_wire_get_qdcount(pkt->wire);
+       int totalsize = 0;
+       int remainingsize = outsize;
 
        if (rcode != NULL) {
                rcode_str = rcode->name;
@@ -893,7 +897,7 @@ char *kr_pkt_text(const knot_pkt_t *pkt)
        }
        flags_to_str(flags, pkt, sizeof(flags));
 
-       char *ptr = mp_printf(mp,
+       totalsize = snprintf(outstr, remainingsize,
                ";; ->>HEADER<<- opcode: %s; status: %s; id: %hu\n"
                ";; Flags: %s QUERY: %hu; ANSWER: %hu; "
                "AUTHORITY: %hu; ADDITIONAL: %hu\n\n",
@@ -903,18 +907,24 @@ char *kr_pkt_text(const knot_pkt_t *pkt)
                knot_wire_get_ancount(pkt->wire),
                knot_wire_get_nscount(pkt->wire),
                knot_wire_get_arcount(pkt->wire));
+       remainingsize = MAX(outsize - totalsize, 0);
 
        if (knot_pkt_has_edns(pkt)) {
-               ptr = print_section_opt(mp, ptr, pkt->opt_rr, knot_wire_get_rcode(pkt->wire));
+               totalsize += print_section_opt(outstr + totalsize, remainingsize,
+                                         pkt->opt_rr, knot_wire_get_rcode(pkt->wire));
+               remainingsize = MAX(outsize - totalsize, 0);
        }
 
        if (qdcount == 1) {
                KR_DNAME_GET_STR(qname, knot_pkt_qname(pkt));
                KR_RRTYPE_GET_STR(rrtype, knot_pkt_qtype(pkt));
-               ptr = mp_printf_append(mp, ptr, ";; QUESTION SECTION\n%s\t\t%s\n", qname, rrtype);
+               totalsize += snprintf(outstr + totalsize, remainingsize,
+                                       ";; QUESTION SECTION\n%s\t\t%s\n", qname, rrtype);
        } else if (qdcount > 1) {
-               ptr = mp_printf_append(mp, ptr, ";; Warning: unsupported QDCOUNT %hu\n", qdcount);
+               totalsize += snprintf(outstr + totalsize, remainingsize,
+                                       ";; Warning: unsupported QDCOUNT %hu\n", qdcount);
        }
+       remainingsize = MAX(outsize - totalsize, 0);
 
        for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
                const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
@@ -923,23 +933,43 @@ char *kr_pkt_text(const knot_pkt_t *pkt)
                        continue;
                }
 
-               ptr = mp_printf_append(mp, ptr, "\n%s\n", snames[i - KNOT_ANSWER]);
+               totalsize += snprintf(outstr + totalsize, remainingsize, "\n%s\n", snames[i - KNOT_ANSWER]);
+               remainingsize = MAX(outsize - totalsize, 0);
                for (unsigned k = 0; k < sec->count; ++k) {
                        const knot_rrset_t *rr = knot_pkt_rr(sec, k);
                        if (rr->type == KNOT_RRTYPE_OPT) {
                                continue;
                        }
                        auto_free char *rr_text = kr_rrset_text(rr);
-                       ptr = mp_printf_append(mp, ptr, "%s", rr_text);
+                       totalsize += snprintf(outstr + totalsize, remainingsize, "%s", rr_text);
+                       remainingsize = MAX(outsize - totalsize, 0);
                }
        }
+       return totalsize;
+}
 
-       /* Close growing buffer and duplicate result before deleting */
-       char *result = strdup(ptr);
-       mp_delete(mp);
-       return result;
+char *kr_pkt_text(const knot_pkt_t *pkt)
+{
+       if (!pkt) {
+               return NULL;
+       }
+       int bufsize = 2048;
+       while (1) {
+               int strsize;
+               auto_free char *buf = malloc(bufsize);
+               if (!buf)
+                       return NULL;
+               strsize = kr_pkt_text_internal(buf, bufsize, pkt);
+               if(strsize < bufsize)
+                       return strdup(buf);
+               else
+                       /* reallocate and try again */
+                       bufsize = strsize + 1;
+       };
 }
 
+
+
 char *kr_rrset_text(const knot_rrset_t *rr)
 {
        if (!rr) {
index 248a4c5cea8b312ab6362ef07bb55cb8bd054964..a9220a11190bbd98f62cff2c927a2321a3da3a27 100644 (file)
@@ -17,6 +17,7 @@
 #include "lib/zonecut.h"
 
 #include "contrib/cleanup.h"
+#include "contrib/macros.h"
 #include "lib/defines.h"
 #include "lib/generic/pack.h"
 #include "lib/layer.h"