summaryrefslogtreecommitdiffstats
path: root/src/lib/mempool-unsafe-datastack.c
blob: 2f2751ddc8d056d766c05aa4f7b82ee1eb842221 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "mempool.h"

/*
 * The unsafe datastack pool is a very thin wrapper around the datastack
 * API.  It is a simpler version of the datastack pool that does not do any
 * sanity checking, it simply forwards the calls to the datastack API.  It
 * exists to allow some internal APIs to make datastack allocations via the
 * pool API.
 *
 * Note to consumers: Consider using the (safe) datastack pool instead of
 * this one.
 *
 * Implementation
 * ==============
 *
 * Creation
 * --------
 *
 * The unsafe datastack pool is created statically and therefore is
 * available at any time after the datastack allocator is initialized.
 *
 * Allocation & Reallocation
 * -------------------------
 *
 * The p_malloc() and p_realloc() calls get directed to t_malloc0() and
 * t_try_realloc(), respectively.  There is no additional per-allocation
 * information to track.
 *
 * Freeing
 * -------
 *
 * A no-op.
 *
 * Clearing
 * --------
 *
 * A no-op.
 *
 * Destruction
 * -----------
 *
 * It is not possible to destroy the unsafe datastack pool.  Any attempt to
 * unref the pool is a no-op.
 */

static const char *pool_unsafe_data_stack_get_name(pool_t pool);
static void pool_unsafe_data_stack_ref(pool_t pool);
static void pool_unsafe_data_stack_unref(pool_t *pool);
static void *pool_unsafe_data_stack_malloc(pool_t pool, size_t size);
static void pool_unsafe_data_stack_free(pool_t pool, void *mem);
static void *pool_unsafe_data_stack_realloc(pool_t pool, void *mem,
					    size_t old_size, size_t new_size);
static void pool_unsafe_data_stack_clear(pool_t pool);
static size_t pool_unsafe_data_stack_get_max_easy_alloc_size(pool_t pool);

static struct pool_vfuncs static_unsafe_data_stack_pool_vfuncs = {
	pool_unsafe_data_stack_get_name,

	pool_unsafe_data_stack_ref,
	pool_unsafe_data_stack_unref,

	pool_unsafe_data_stack_malloc,
	pool_unsafe_data_stack_free,

	pool_unsafe_data_stack_realloc,

	pool_unsafe_data_stack_clear,
	pool_unsafe_data_stack_get_max_easy_alloc_size
};

static struct pool static_unsafe_data_stack_pool = {
	.v = &static_unsafe_data_stack_pool_vfuncs,

	.alloconly_pool = TRUE,
	.datastack_pool = TRUE
};

pool_t unsafe_data_stack_pool = &static_unsafe_data_stack_pool;

static const char *pool_unsafe_data_stack_get_name(pool_t pool ATTR_UNUSED)
{
	return "unsafe data stack";
}

static void pool_unsafe_data_stack_ref(pool_t pool ATTR_UNUSED)
{
}

static void pool_unsafe_data_stack_unref(pool_t *pool ATTR_UNUSED)
{
}

static void *pool_unsafe_data_stack_malloc(pool_t pool ATTR_UNUSED,
					   size_t size)
{
	return t_malloc0(size);
}

static void pool_unsafe_data_stack_free(pool_t pool ATTR_UNUSED,
					void *mem ATTR_UNUSED)
{
}

static void *pool_unsafe_data_stack_realloc(pool_t pool ATTR_UNUSED,
					    void *mem,
					    size_t old_size, size_t new_size)
{
	void *new_mem;

	/* @UNSAFE */
	if (old_size >= new_size)
		return mem;

	if (!t_try_realloc(mem, new_size)) {
		new_mem = t_malloc_no0(new_size);
		memcpy(new_mem, mem, old_size);
		mem = new_mem;
	}

	memset((char *) mem + old_size, 0, new_size - old_size);
	return mem;
}

static void pool_unsafe_data_stack_clear(pool_t pool ATTR_UNUSED)
{
}

static size_t
pool_unsafe_data_stack_get_max_easy_alloc_size(pool_t pool ATTR_UNUSED)
{
	return t_get_bytes_available();
}