1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#pragma once
40
41#include <stdlib.h>
42#include <toku_portability.h>
43
44/* Percona memory allocation functions and macros.
45 * These are functions for malloc and free */
46
47int toku_memory_startup(void) __attribute__((constructor));
48void toku_memory_shutdown(void) __attribute__((destructor));
49
50/* Generally: errno is set to 0 or a value to indicate problems. */
51
52// Everything should call toku_malloc() instead of malloc(), and toku_calloc() instead of calloc()
53// That way the tests can can, e.g., replace the malloc function using toku_set_func_malloc().
54void *toku_calloc(size_t nmemb, size_t size) __attribute__((__visibility__("default")));
55void *toku_xcalloc(size_t nmemb, size_t size) __attribute__((__visibility__("default")));
56void *toku_malloc(size_t size) __attribute__((__visibility__("default")));
57void *toku_malloc_aligned(size_t alignment, size_t size) __attribute__((__visibility__("default")));
58
59// xmalloc aborts instead of return NULL if we run out of memory
60void *toku_xmalloc(size_t size) __attribute__((__visibility__("default")));
61void *toku_xrealloc(void*, size_t size) __attribute__((__visibility__("default")));
62void *toku_xmalloc_aligned(size_t alignment, size_t size) __attribute__((__visibility__("default")));
63// Effect: Perform a os_malloc_aligned(size) with the additional property that the returned pointer is a multiple of ALIGNMENT.
64// Fail with a resource_assert if the allocation fails (don't return an error code).
65// If the alloc_aligned function has been set then call it instead.
66// Requires: alignment is a power of two.
67
68void toku_free(void*) __attribute__((__visibility__("default")));
69void *toku_realloc(void *, size_t size) __attribute__((__visibility__("default")));
70void *toku_realloc_aligned(size_t alignment, void *p, size_t size) __attribute__((__visibility__("default")));
71// Effect: Perform a os_realloc_aligned(alignment, p, size) which has the additional property that the returned pointer is a multiple of ALIGNMENT.
72// If the malloc_aligned function has been set then call it instead.
73// Requires: alignment is a power of two.
74
75size_t toku_malloc_usable_size(void *p) __attribute__((__visibility__("default")));
76
77/* MALLOC is a macro that helps avoid a common error:
78 * Suppose I write
79 * struct foo *x = malloc(sizeof(struct foo));
80 * That works fine. But if I change it to this, I've probably made an mistake:
81 * struct foo *x = malloc(sizeof(struct bar));
82 * It can get worse, since one might have something like
83 * struct foo *x = malloc(sizeof(struct foo *))
84 * which looks reasonable, but it allocoates enough to hold a pointer instead of the amount needed for the struct.
85 * So instead, write
86 * struct foo *MALLOC(x);
87 * and you cannot go wrong.
88 */
89#define MALLOC(v) CAST_FROM_VOIDP(v, toku_malloc(sizeof(*v)))
90/* MALLOC_N is like calloc(Except no 0ing of data): It makes an array. Write
91 * int *MALLOC_N(5,x);
92 * to make an array of 5 integers.
93 */
94#define MALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_malloc((n)*sizeof(*v)))
95#define MALLOC_N_ALIGNED(align, n, v) CAST_FROM_VOIDP(v, toku_malloc_aligned((align), (n)*sizeof(*v)))
96
97
98//CALLOC_N is like calloc with auto-figuring out size of members
99#define CALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_calloc((n), sizeof(*v)))
100
101#define CALLOC(v) CALLOC_N(1,v)
102
103#define REALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_realloc(v, (n)*sizeof(*v)))
104#define REALLOC_N_ALIGNED(align, n,v) CAST_FROM_VOIDP(v, toku_realloc_aligned((align), v, (n)*sizeof(*v)))
105
106// XMALLOC macros are like MALLOC except they abort if the operation fails
107#define XMALLOC(v) CAST_FROM_VOIDP(v, toku_xmalloc(sizeof(*v)))
108#define XMALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_xmalloc((n)*sizeof(*v)))
109#define XCALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_xcalloc((n), (sizeof(*v))))
110#define XCALLOC(v) XCALLOC_N(1,(v))
111#define XREALLOC(v,s) CAST_FROM_VOIDP(v, toku_xrealloc(v, s))
112#define XREALLOC_N(n,v) CAST_FROM_VOIDP(v, toku_xrealloc(v, (n)*sizeof(*v)))
113
114#define XMALLOC_N_ALIGNED(align, n, v) CAST_FROM_VOIDP(v, toku_xmalloc_aligned((align), (n)*sizeof(*v)))
115
116#define XMEMDUP(dst, src) CAST_FROM_VOIDP(dst, toku_xmemdup(src, sizeof(*src)))
117#define XMEMDUP_N(dst, src, len) CAST_FROM_VOIDP(dst, toku_xmemdup(src, len))
118
119// ZERO_ARRAY writes zeroes to a stack-allocated array
120#define ZERO_ARRAY(o) do { memset((o), 0, sizeof (o)); } while (0)
121// ZERO_STRUCT writes zeroes to a stack-allocated struct
122#define ZERO_STRUCT(o) do { memset(&(o), 0, sizeof (o)); } while (0)
123
124/* Copy memory. Analogous to strdup() */
125void *toku_memdup (const void *v, size_t len);
126/* Toku-version of strdup. Use this so that it calls toku_malloc() */
127char *toku_strdup (const char *s) __attribute__((__visibility__("default")));
128/* Toku-version of strndup. Use this so that it calls toku_malloc() */
129char *toku_strndup(const char *s, size_t n)
130 __attribute__((__visibility__("default")));
131/* Copy memory. Analogous to strdup() Crashes instead of returning NULL */
132void *toku_xmemdup (const void *v, size_t len) __attribute__((__visibility__("default")));
133/* Toku-version of strdup. Use this so that it calls toku_xmalloc() Crashes instead of returning NULL */
134char *toku_xstrdup (const char *s) __attribute__((__visibility__("default")));
135
136void toku_malloc_cleanup (void); /* Before exiting, call this function to free up any internal data structures from toku_malloc. Otherwise valgrind will complain of memory leaks. */
137
138/* Check to see if everything malloc'd was free. Might be a no-op depending on how memory.c is configured. */
139void toku_memory_check_all_free (void);
140/* Check to see if memory is "sane". Might be a no-op. Probably better to simply use valgrind. */
141void toku_do_memory_check(void);
142
143typedef void *(*malloc_fun_t)(size_t);
144typedef void (*free_fun_t)(void*);
145typedef void *(*realloc_fun_t)(void*,size_t);
146typedef void *(*malloc_aligned_fun_t)(size_t /*alignment*/, size_t /*size*/);
147typedef void *(*realloc_aligned_fun_t)(size_t /*alignment*/, void */*pointer*/, size_t /*size*/);
148
149void toku_set_func_malloc(malloc_fun_t f);
150void toku_set_func_xmalloc_only(malloc_fun_t f);
151void toku_set_func_malloc_only(malloc_fun_t f);
152void toku_set_func_realloc(realloc_fun_t f);
153void toku_set_func_xrealloc_only(realloc_fun_t f);
154void toku_set_func_realloc_only(realloc_fun_t f);
155void toku_set_func_free(free_fun_t f);
156
157typedef struct memory_status {
158 uint64_t malloc_count; // number of malloc operations
159 uint64_t free_count; // number of free operations
160 uint64_t realloc_count; // number of realloc operations
161 uint64_t malloc_fail; // number of malloc operations that failed
162 uint64_t realloc_fail; // number of realloc operations that failed
163 uint64_t requested; // number of bytes requested
164 uint64_t used; // number of bytes used (requested + overhead), obtained from malloc_usable_size()
165 uint64_t freed; // number of bytes freed;
166 uint64_t max_requested_size; // largest attempted allocation size
167 uint64_t last_failed_size; // size of the last failed allocation attempt
168 volatile uint64_t max_in_use; // maximum memory footprint (used - freed), approximate (not worth threadsafety overhead for exact)
169 const char *mallocator_version;
170 uint64_t mmap_threshold;
171} LOCAL_MEMORY_STATUS_S, *LOCAL_MEMORY_STATUS;
172
173void toku_memory_get_status(LOCAL_MEMORY_STATUS s);
174
175// Effect: Like toku_memory_footprint, except instead of passing p,
176// we pass toku_malloc_usable_size(p).
177size_t toku_memory_footprint_given_usable_size(size_t touched, size_t usable);
178
179// Effect: Return an estimate how how much space an object is using, possibly by
180// using toku_malloc_usable_size(p).
181// If p is NULL then returns 0.
182size_t toku_memory_footprint(void * p, size_t touched);
183