forked from redis/redis
-
Notifications
You must be signed in to change notification settings - Fork 4
Collapse file tree
Files
Search this repository
/
Copy pathzmalloc.c
More file actions
More file actions
Latest commit
1089 lines (950 loc) · 32.8 KB
/
zmalloc.c
File metadata and controls
1089 lines (950 loc) · 32.8 KB
Edit and raw actions
OlderNewer
1
/* zmalloc - total amount of allocated memory aware version of malloc()
2
*
3
* Copyright (c) 2009-Present, Redis Ltd.
4
* All rights reserved.
5
*
6
* Licensed under your choice of (a) the Redis Source Available License 2.0
7
* (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
8
* GNU Affero General Public License v3 (AGPLv3).
9
*/
10
11
#include "fmacros.h"
12
#include "config.h"
13
#include "solarisfixes.h"
14
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <stdint.h>
18
#include <unistd.h>
19
20
#ifdef __linux__
21
#include <sys/mman.h>
22
#endif
23
24
/* This function provide us access to the original libc free(). This is useful
25
* for instance to free results obtained by backtrace_symbols(). We need
26
* to define this function before including zmalloc.h that may shadow the
27
* free implementation if we use jemalloc or another non standard allocator. */
28
void zlibc_free(void *ptr) {
29
free(ptr);
30
}
31
32
#include <string.h>
33
#include "zmalloc.h"
34
#include "atomicvar.h"
35
#include "redisassert.h"
36
37
#define UNUSED(x) ((void)(x))
38
39
#ifdef HAVE_MALLOC_SIZE
40
#define PREFIX_SIZE (0)
41
#else
42
/* Use at least 8 bytes alignment on all systems. */
43
#if SIZE_MAX < 0xffffffffffffffffull
44
#define PREFIX_SIZE 8
45
#else
46
#define PREFIX_SIZE (sizeof(size_t))
47
#endif
48
#endif
49
50
/* When using the libc allocator, use a minimum allocation size to match the
51
* jemalloc behavior that doesn't return NULL in this case.
52
*/
53
#define MALLOC_MIN_SIZE(x) ((x) > 0 ? (x) : sizeof(long))
54
55
/* Explicitly override malloc/free etc when using tcmalloc. */
56
#if defined(USE_TCMALLOC)
57
#define malloc(size) tc_malloc(size)
58
#define calloc(count,size) tc_calloc(count,size)
59
#define realloc(ptr,size) tc_realloc(ptr,size)
60
#define free(ptr) tc_free(ptr)
61
/* Explicitly override malloc/free etc when using jemalloc. */
62
#elif defined(USE_JEMALLOC)
63
#define malloc(size) je_malloc(size)
64
#define calloc(count,size) je_calloc(count,size)
65
#define realloc(ptr,size) je_realloc(ptr,size)
66
#define free(ptr) je_free(ptr)
67
#define mallocx(size,flags) je_mallocx(size,flags)
68
#define rallocx(ptr,size,flags) je_rallocx(ptr,size,flags)
69
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
70
#endif
71
72
#define MAX_THREADS 16 /* Keep it a power of 2 so we can use '&' instead of '%'. */
73
#define THREAD_MASK (MAX_THREADS - 1)
74
75
typedef struct used_memory_entry {
76
redisAtomic long long used_memory;
77
char padding[CACHE_LINE_SIZE - sizeof(long long)];
78
} used_memory_entry;
79
80
static __attribute__((aligned(CACHE_LINE_SIZE))) used_memory_entry used_memory[MAX_THREADS];
81
static redisAtomic size_t num_active_threads = 0;
82
static __thread long my_thread_index = -1;
83
84
static inline void init_my_thread_index(void) {
85
if (unlikely(my_thread_index == -1)) {
86
atomicGetIncr(num_active_threads, my_thread_index, 1);
87
my_thread_index &= THREAD_MASK;
88
}
89
}
90
91
static void update_zmalloc_stat_alloc(long long num) {
92
init_my_thread_index();
93
atomicIncr(used_memory[my_thread_index].used_memory, num);
94
}
95
96
static void update_zmalloc_stat_free(long long num) {
97
init_my_thread_index();
98
atomicDecr(used_memory[my_thread_index].used_memory, num);
99
}
100
101
static void zmalloc_default_oom(size_t size) {