master
c 172 lines 4.45 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "judy-malloc.h"
4
5 // --------------------------------------------------------------------------------------------------------------------
6 // Judy using ARAL
7
8 #define MAX_JUDY_SIZE_TO_ARAL 24
9 static bool judy_sizes_config[MAX_JUDY_SIZE_TO_ARAL + 1] = {
10 [3] = true,
11 [4] = true,
12 [5] = true,
13 [6] = true,
14 [7] = true,
15 [8] = true,
16 [10] = true,
17 [11] = true,
18 [15] = true,
19 [23] = true,
20 };
21 static ARAL *judy_sizes_aral[MAX_JUDY_SIZE_TO_ARAL + 1] = { 0 };
22
23 struct aral_statistics judy_sizes_aral_statistics = { 0 };
24
25 static void aral_judy_init(void) {
26 for(size_t Words = 0; Words <= MAX_JUDY_SIZE_TO_ARAL; Words++)
27 if(judy_sizes_config[Words]) {
28 char buf[30+1];
29 snprintfz(buf, sizeof(buf) - 1, "judy-%zu", Words * sizeof(Word_t));
30 judy_sizes_aral[Words] = aral_create(
31 buf,
32 Words * sizeof(Word_t),
33 0,
34 0,
35 &judy_sizes_aral_statistics,
36 NULL, NULL, false, false, false);
37 }
38 }
39
40 size_t judy_aral_free_bytes(void) {
41 return aral_free_bytes_from_stats(&judy_sizes_aral_statistics);
42 }
43
44 size_t judy_aral_structures(void) {
45 return aral_structures_bytes_from_stats(&judy_sizes_aral_statistics);
46 }
47
48 struct aral_statistics *judy_aral_statistics(void) {
49 return &judy_sizes_aral_statistics;
50 }
51
52 static ARAL *judy_size_aral(Word_t Words) {
53 if(Words <= MAX_JUDY_SIZE_TO_ARAL)
54 return judy_sizes_aral[Words];
55
56 return NULL;
57 }
58
59 // --------------------------------------------------------------------------------------------------------------------
60 // Judy memory tracking
61
62 static __thread int64_t judy_allocated = 0;
63
64 ALWAYS_INLINE void JudyAllocThreadPulseReset(void) {
65 judy_allocated = 0;
66 }
67
68 ALWAYS_INLINE int64_t JudyAllocThreadPulseGetAndReset(void) {
69 int64_t rc = judy_allocated;
70 judy_allocated = 0;
71 return rc;
72 }
73
74 // --------------------------------------------------------------------------------------------------------------------
75 // Judy dedicated jemalloc arena
76
77 static unsigned jemalloc_arena_index __maybe_unused = 0;
78 static bool jemalloc_initialized __maybe_unused = false;
79
80 #ifdef HAVE_JEMALLOC_ARENA_API
81 #include <jemalloc/jemalloc.h>
82 static void jemalloc_init(void) {
83 // Create shared arena
84 size_t sz = sizeof(unsigned);
85 if (mallctl("arenas.create", &jemalloc_arena_index, &sz, NULL, 0) != 0)
86 return;
87
88 // Disable thread cache for direct arena access
89 int cache_enabled = 0;
90 if (mallctl("thread.tcache.enabled", NULL, NULL, &cache_enabled, sizeof(bool)) != 0)
91 return;
92
93 jemalloc_initialized = true;
94 }
95
96 static void *jemalloc_malloc(Word_t Words) {
97 return mallocx(Words * sizeof(Word_t), MALLOCX_ARENA(jemalloc_arena_index));
98 }
99
100 static void jemalloc_free(void * PWord, Word_t Words __maybe_unused) {
101 if(PWord)
102 dallocx(PWord, MALLOCX_ARENA(jemalloc_arena_index));
103 }
104 #endif
105
106 // --------------------------------------------------------------------------------------------------------------------
107 // Judy API
108
109 inline Word_t JudyMalloc(Word_t Words)
110 {
111 Word_t Addr;
112
113 #ifdef HAVE_JEMALLOC_ARENA_API
114 if(jemalloc_initialized)
115 Addr = (Word_t)jemalloc_malloc(Words);
116 else
117 #endif
118 {
119 ARAL *ar = judy_size_aral(Words);
120 if (ar)
121 Addr = (Word_t)aral_mallocz(ar);
122 else
123 Addr = (Word_t)mallocz(Words * sizeof(Word_t));
124 }
125
126 judy_allocated += Words * sizeof(Word_t);
127
128 return(Addr);
129 }
130
131 inline void JudyFree(void * PWord, Word_t Words) {
132 #ifdef HAVE_JEMALLOC_ARENA_API
133 if(jemalloc_initialized)
134 jemalloc_free(PWord, Words);
135 else
136 #endif
137 {
138 ARAL *ar = judy_size_aral(Words);
139 if (ar)
140 aral_freez(ar, PWord);
141 else
142 freez(PWord);
143 }
144
145 judy_allocated -= Words * sizeof(Word_t);
146 }
147
148 Word_t JudyMallocVirtual(Word_t Words) {
149 return JudyMalloc(Words);
150 }
151
152 void JudyFreeVirtual(void * PWord, Word_t Words) {
153 JudyFree(PWord, Words);
154 }
155
156 // --------------------------------------------------------------------------------------------------------------------
157 // initialization
158
159 void libjudy_malloc_init(void) {
160 // IMPORTANT: this is not called on external plugins
161 // the allocator should run even if this is not called
162
163 (void)jemalloc_initialized;
164 (void)jemalloc_arena_index;
165
166 #ifdef HAVE_JEMALLOC_ARENA_API
167 jemalloc_init();
168 if(!jemalloc_initialized)
169 #endif
170 aral_judy_init();
171 }
172