mempool-system.c revision cbe4d8212ec8b9014ae7ae892e90abb98a15d797
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* @UNSAFE: whole file */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "safe-memset.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "mempool.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#ifndef HAVE_MALLOC_USABLE_SIZE
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* no extra includes needed */
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#elif defined (HAVE_MALLOC_NP_H)
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen# include <malloc_np.h> /* FreeBSD */
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#elif defined (HAVE_MALLOC_H)
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen# include <malloc.h> /* Linux */
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen#endif
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define CLEAR_CHR 0xde
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic const char *pool_system_get_name(pool_t pool);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void pool_system_ref(pool_t pool);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void pool_system_unref(pool_t *pool);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void *pool_system_malloc(pool_t pool, size_t size);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void *pool_system_realloc(pool_t pool, void *mem,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen size_t old_size, size_t new_size);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void pool_system_clear(pool_t pool);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic size_t pool_system_get_max_easy_alloc_size(pool_t pool);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct pool_vfuncs static_system_pool_vfuncs = {
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen pool_system_get_name,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen pool_system_ref,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen pool_system_unref,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pool_system_malloc,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pool_system_free,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pool_system_realloc,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen pool_system_clear,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen pool_system_get_max_easy_alloc_size
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen};
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainenstruct pool static_system_pool = {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen .v = &static_system_pool_vfuncs,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen .alloconly_pool = FALSE,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen .datastack_pool = FALSE
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen};
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenpool_t system_pool = &static_system_pool;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenstatic const char *pool_system_get_name(pool_t pool ATTR_UNUSED)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return "system";
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen}
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainenstatic void pool_system_ref(pool_t pool ATTR_UNUSED)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainenstatic void pool_system_unref(pool_t *pool ATTR_UNUSED)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void *pool_system_malloc(pool_t pool ATTR_UNUSED, size_t size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen void *mem;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen#ifdef DEBUG
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen int old_errno = errno;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen#endif
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen if (unlikely(size == 0 || size > SSIZE_T_MAX))
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen mem = calloc(size, 1);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (unlikely(mem == NULL)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_fatal_status(FATAL_OUTOFMEM, "pool_system_malloc(%"PRIuSIZE_T
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "): Out of memory", size);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen }
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen#ifdef DEBUG
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we rely on errno not changing. it shouldn't. */
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen i_assert(errno == old_errno);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#endif
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen return mem;
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainenvoid pool_system_free(pool_t pool ATTR_UNUSED, void *mem ATTR_UNUSED)
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen{
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen#ifdef DEBUG
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen int old_errno = errno;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if defined(HAVE_MALLOC_USABLE_SIZE) && defined(DEBUG)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen safe_memset(mem, CLEAR_CHR, malloc_usable_size(mem));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#endif
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen free(mem);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#ifdef DEBUG
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* we rely on errno not changing. it shouldn't. */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i_assert(errno == old_errno);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#endif
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void *pool_system_realloc(pool_t pool ATTR_UNUSED, void *mem,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen size_t old_size, size_t new_size)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (unlikely(new_size == 0 || new_size > SSIZE_T_MAX))
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (mem == NULL) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen i_assert(old_size == 0);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return pool_system_malloc(pool, new_size);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen#if defined(HAVE_MALLOC_USABLE_SIZE)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_assert(old_size == (size_t)-1 || mem == NULL ||
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen old_size <= malloc_usable_size(mem));
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen#endif
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen mem = realloc(mem, new_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (unlikely(mem == NULL)) {
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen i_fatal_status(FATAL_OUTOFMEM, "pool_system_realloc(%"PRIuSIZE_T
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen "): Out of memory", new_size);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen if (old_size < new_size) {
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen /* clear new data */
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen memset((char *) mem + old_size, 0, new_size - old_size);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return mem;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstatic void ATTR_NORETURN
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainenpool_system_clear(pool_t pool ATTR_UNUSED)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen{
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen i_panic("pool_system_clear() must not be called");
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainenstatic size_t pool_system_get_max_easy_alloc_size(pool_t pool ATTR_UNUSED)
4b41116563110d00330896a568eff1078c382827Timo Sirainen{
4b41116563110d00330896a568eff1078c382827Timo Sirainen return 0;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen}
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen