changeset 5356:48fe4fe9ef64 HEAD

Added system_clean_pool. default_pool is now set statically, so it can be changed before calling lib_init(). Use malloc_usable_size() if it's available for asserts and for implementing system_clean_pool.
author Timo Sirainen <tss@iki.fi>
date Sun, 18 Mar 2007 03:57:11 +0200
parents e83bf216cec2
children ac0ef8053692
files configure.in src/lib/Makefile.am src/lib/imem.c src/lib/imem.h src/lib/mempool-system-clean.c src/lib/mempool-system.c src/lib/mempool.h
diffstat 7 files changed, 186 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Sun Mar 18 03:53:19 2007 +0200
+++ b/configure.in	Sun Mar 18 03:57:11 2007 +0200
@@ -15,7 +15,7 @@
 AC_PROG_LIBTOOL
 AM_ICONV
 
-AC_CHECK_HEADERS(strings.h stdint.h unistd.h dirent.h \
+AC_CHECK_HEADERS(strings.h stdint.h unistd.h dirent.h malloc.h \
   sys/uio.h sys/sysmacros.h sys/resource.h sys/select.h libgen.h \
   sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h jfs/quota.h \
   mntent.h sys/mnttab.h sys/event.h sys/time.h sys/mkdev.h linux/dqblk_xfs.h \
@@ -436,7 +436,8 @@
                strcasecmp stricmp vsnprintf vsyslog writev pread \
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
 	       strtoull strtouq setpriority quotactl getmntent kqueue kevent \
-	       getrusage backtrace_symbols walkcontext dirfd)
+	       getrusage backtrace_symbols walkcontext dirfd \
+	       malloc_usable_size)
 
 dnl * I/O loop function
 have_ioloop=no
@@ -1858,6 +1859,14 @@
 AC_SUBST(sql_drivers)
 
 dnl **
+dnl ** Settings
+dnl **
+
+dnl get a list of setting .[ch] files, but list .h files first
+SETTING_FILES=`find $srcdir/src -name '*settings.[[ch]]' ! -name all-settings.[[ch]] | sed -e s,$srcdir/src,./src,g -e 's,./src,$(top_srcdir)/src,g' -e 's/^\(.*\)\(.\)$/\2 \1\2/' | sort -r | sed s/^..//|tr '\n' ' '`
+AC_SUBST(SETTING_FILES)
+
+dnl **
 dnl ** Plugins
 dnl **
 
@@ -1889,6 +1898,7 @@
 src/lib-imap/Makefile
 src/lib-index/Makefile
 src/lib-mail/Makefile
+src/lib-master/Makefile
 src/lib-ntlm/Makefile
 src/lib-otp/Makefile
 src/lib-settings/Makefile
@@ -1908,6 +1918,8 @@
 src/master/Makefile
 src/pop3/Makefile
 src/pop3-login/Makefile
+src/config/Makefile
+src/log/Makefile
 src/util/Makefile
 src/plugins/Makefile
 src/plugins/acl/Makefile
--- a/src/lib/Makefile.am	Sun Mar 18 03:53:19 2007 +0200
+++ b/src/lib/Makefile.am	Sun Mar 18 03:57:11 2007 +0200
@@ -53,6 +53,7 @@
 	mempool-alloconly.c \
 	mempool-datastack.c \
 	mempool-system.c \
+	mempool-system-clean.c \
 	mempool-unsafe-datastack.c \
 	mkdir-parents.c \
 	mmap-anon.c \
--- a/src/lib/imem.c	Sun Mar 18 03:53:19 2007 +0200
+++ b/src/lib/imem.c	Sun Mar 18 03:57:11 2007 +0200
@@ -2,7 +2,7 @@
 
 #include "lib.h"
 
-pool_t default_pool;
+pool_t default_pool = &static_system_pool;
 
 void *i_malloc(size_t size)
 {
@@ -73,8 +73,3 @@
 	va_end(args);
         return ret;
 }
-
-void imem_init(void)
-{
-	default_pool = system_pool;
-}
--- a/src/lib/imem.h	Sun Mar 18 03:53:19 2007 +0200
+++ b/src/lib/imem.h	Sun Mar 18 03:57:11 2007 +0200
@@ -28,6 +28,4 @@
 
 char *i_strconcat(const char *str1, ...)  __attr_sentinel__ __attr_malloc__;
 
-void imem_init(void);
-
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/mempool-system-clean.c	Sun Mar 18 03:57:11 2007 +0200
@@ -0,0 +1,158 @@
+/* Copyright (c) 2007 Timo Sirainen */
+
+/* @UNSAFE: whole file */
+
+#include "lib.h"
+#include "safe-memset.h"
+#include "mempool.h"
+
+#ifdef HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+#include <stdlib.h>
+
+#ifdef HAVE_GC_GC_H
+#  include <gc/gc.h>
+#elif defined (HAVE_GC_H)
+#  include <gc.h>
+#endif
+
+static const char *pool_system_clean_get_name(pool_t pool);
+static void pool_system_clean_ref(pool_t pool);
+static void pool_system_clean_unref(pool_t *pool);
+static void *pool_system_clean_malloc(pool_t pool, size_t size);
+static void pool_system_clean_free(pool_t pool, void *mem);
+static void *pool_system_clean_realloc(pool_t pool, void *mem,
+				       size_t old_size, size_t new_size);
+static void pool_system_clean_clear(pool_t pool);
+static size_t pool_system_clean_get_max_easy_alloc_size(pool_t pool);
+
+static struct pool_vfuncs static_system_clean_pool_vfuncs = {
+	pool_system_clean_get_name,
+
+	pool_system_clean_ref,
+	pool_system_clean_unref,
+
+	pool_system_clean_malloc,
+	pool_system_clean_free,
+
+	pool_system_clean_realloc,
+
+	pool_system_clean_clear,
+	pool_system_clean_get_max_easy_alloc_size
+};
+
+static struct pool static_system_clean_pool = {
+	MEMBER(v) &static_system_clean_pool_vfuncs,
+
+	MEMBER(alloconly_pool) FALSE,
+	MEMBER(datastack_pool) FALSE
+};
+
+pool_t system_clean_pool = &static_system_clean_pool;
+
+static const char *pool_system_clean_get_name(pool_t pool __attr_unused__)
+{
+	return "system clean";
+}
+
+static void pool_system_clean_ref(pool_t pool __attr_unused__)
+{
+}
+
+static void pool_system_clean_unref(pool_t *pool __attr_unused__)
+{
+}
+
+static size_t mem_get_size(void *mem)
+{
+#ifdef USE_GC
+	return GC_size(mem);
+#elif defined(HAVE_MALLOC_USABLE_SIZE)
+	return malloc_usable_size(mem);
+#else
+	return ((size_t *)mem)[-1];
+#endif
+}
+
+static void *pool_system_clean_malloc(pool_t pool __attr_unused__, size_t size)
+{
+	void *mem;
+
+	if (size == 0 || size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
+
+#ifdef USE_GC
+	mem = GC_malloc(size);
+#else
+#ifndef HAVE_MALLOC_USABLE_SIZE
+	size += sizeof(size_t);
+#endif
+	mem = calloc(size, 1);
+#endif
+	if (mem == NULL) {
+		i_fatal_status(FATAL_OUTOFMEM,
+			       "pool_system_clean_malloc(): Out of memory");
+	}
+#if !defined(USE_GC) && !defined(HAVE_MALLOC_USABLE_SIZE)
+	{
+		size_t *saved_size = mem;
+
+		*saved_size = size;
+		mem = saved_size + 1;
+	}
+#endif
+	return mem;
+}
+
+static void pool_system_clean_free(pool_t pool __attr_unused__, void *mem)
+{
+	if (mem != NULL) {
+		safe_memset(mem, 0, mem_get_size(mem));
+#ifndef USE_GC
+#ifndef HAVE_MALLOC_USABLE_SIZE
+		mem = (size_t *)mem - 1;
+#endif
+		free(mem);
+#endif
+	}
+}
+
+static void *pool_system_clean_realloc(pool_t pool __attr_unused__, void *mem,
+				       size_t old_size, size_t new_size)
+{
+	void *new_mem;
+
+	if (new_size == 0 || new_size > SSIZE_T_MAX)
+		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
+
+	new_mem = pool_system_clean_malloc(pool, new_size);
+	if (mem != NULL) {
+#if !defined(USE_GC) && defined(HAVE_MALLOC_USABLE_SIZE)
+		i_assert(old_size == (size_t)-1 ||
+			 old_size <= malloc_usable_size(mem));
+#endif
+		memcpy(new_mem, mem, mem_get_size(mem));
+		pool_system_clean_free(pool, mem);
+
+		if (old_size < new_size) {
+			/* clear new data */
+			memset((char *)new_mem + old_size, 0,
+			       new_size - old_size);
+		}
+	}
+
+        return new_mem;
+}
+
+static void __attr_noreturn__
+pool_system_clean_clear(pool_t pool __attr_unused__)
+{
+	i_panic("pool_system_clean_clear() must not be called");
+}
+
+static size_t
+pool_system_clean_get_max_easy_alloc_size(pool_t pool __attr_unused__)
+{
+	return 0;
+}
--- a/src/lib/mempool-system.c	Sun Mar 18 03:53:19 2007 +0200
+++ b/src/lib/mempool-system.c	Sun Mar 18 03:57:11 2007 +0200
@@ -6,6 +6,9 @@
 #include "mempool.h"
 
 #include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
 
 #ifdef HAVE_GC_GC_H
 #  include <gc/gc.h>
@@ -38,14 +41,13 @@
 	pool_system_get_max_easy_alloc_size
 };
 
-static struct pool static_system_pool = {
+struct pool static_system_pool = {
 	MEMBER(v) &static_system_pool_vfuncs,
 
 	MEMBER(alloconly_pool) FALSE,
 	MEMBER(datastack_pool) FALSE
 };
 
-
 pool_t system_pool = &static_system_pool;
 
 static const char *pool_system_get_name(pool_t pool __attr_unused__)
@@ -105,6 +107,10 @@
 			       "pool_system_realloc(): Out of memory");
 	}
 
+#if !defined(USE_GC) && defined(HAVE_MALLOC_USABLE_SIZE)
+	i_assert(old_size == (size_t)-1 || mem == NULL ||
+		 old_size <= malloc_usable_size(mem));
+#endif
 	if (old_size < new_size) {
                 /* clear new data */
 		memset((char *) mem + old_size, 0, new_size - old_size);
--- a/src/lib/mempool.h	Sun Mar 18 03:53:19 2007 +0200
+++ b/src/lib/mempool.h	Sun Mar 18 03:57:11 2007 +0200
@@ -48,6 +48,10 @@
 
 /* system_pool uses calloc() + realloc() + free() */
 extern pool_t system_pool;
+extern struct pool static_system_pool;
+/* Similar to pool_alloconly_create_clean(), but uses system_pool to
+   allocate the memory. */
+extern pool_t system_clean_pool;
 
 /* memory allocated from data_stack is valid only until next t_pop() call.
    No checks are performed. */