Skip to content

Commit fc609d5

Browse files
committed
Replace system allocator with the second instance of linear BA
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 5256637 commit fc609d5

File tree

4 files changed

+89
-103
lines changed

4 files changed

+89
-103
lines changed

src/proxy_lib/proxy_lib.c

Lines changed: 89 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@
3434

3535
/*
3636
* The UMF proxy library uses three memory allocators:
37-
* 1) the internal linear base allocator (LBA) based on the anonymous mapped memory
38-
* 2) the system allocator (libc malloc on Linux for example)
37+
* 1) the first "LEAK" instance of the internal linear base allocator
38+
* based on the anonymous mapped memory that will NOT be destroyed (with API ba_leak_*()).
39+
* 2) the second instance of the internal linear base allocator
40+
* based on the anonymous mapped memory that will be destroyed (with API ba_*()).
3941
* 3) the main one - UMF pool allocator.
4042
*
4143
* Ad 1)
42-
* The internal linear base allocator (LBA) is used from the very beginning
43-
* to the start of the constructor of the proxy library to allocate memory
44-
* for OS specific structures used during loading and starting applications
45-
* (for example _dl_init() and _dl_fini() on Linux storing arrays of all
44+
* The first "LEAK" instance of the internal linear base allocator is used
45+
* from the very beginning to the start of the constructor of the proxy library
46+
* to allocate memory for OS specific structures used during loading and starting
47+
* applications (for example _dl_init() and _dl_fini() on Linux storing arrays of all
4648
* constructors and destructors that have to be called). That memory will be leaked
4749
* on purpose (we believe OS will free it), because we cannot free the memory
4850
* containing array of destructors that have to be called at the end.
@@ -53,19 +55,21 @@
5355
* - malloc(72704)
5456
*
5557
* Ad 2)
56-
* The system allocator is used from the start of the constructor of the proxy library
57-
* to the creation of a UMF pool to allocate memory needed by umfMemoryProviderCreate()
58-
* and umfPoolCreate(). It will be freed by the system allocator.
58+
* The second instance of the internal linear base allocator is used
59+
* from the start of the constructor of the proxy library to the creation of a UMF pool
60+
* to allocate memory needed by umfMemoryProviderCreate() and umfPoolCreate().
61+
* It is created at the start of the constructor of the proxy library
62+
* and destroyed at the end of the destructor of the proxy library.
5963
*
6064
* Ad 3)
6165
* The UMF pool allocator (the main one) is used from the creation to the destruction
6266
* of a UMF pool to allocate memory needed by an application. It should be freed
6367
* by an application.
6468
*/
6569

66-
static UTIL_ONCE_FLAG Base_alloc_initialized = UTIL_ONCE_FLAG_INIT;
67-
static UTIL_ONCE_FLAG alloc_hooks_are_initialized = UTIL_ONCE_FLAG_INIT;
70+
static UTIL_ONCE_FLAG Base_alloc_leak_initialized = UTIL_ONCE_FLAG_INIT;
6871

72+
static umf_ba_linear_pool_t *Base_alloc_leak = NULL;
6973
static umf_ba_linear_pool_t *Base_alloc = NULL;
7074
static int Constructors_started = 0;
7175
static umf_memory_provider_handle_t OS_memory_provider = NULL;
@@ -84,7 +88,13 @@ aligned_alloc_func_t System_aligned_alloc_func;
8488
/*** The constructor and destructor of the proxy library *********************/
8589
/*****************************************************************************/
8690

91+
static void ba_create(void);
92+
static void ba_destroy(void);
93+
8794
void proxy_lib_create_common(void) {
95+
// create the second instance of linear base allocator
96+
ba_create();
97+
8898
// The constructors of libraries were started. Stop using the linear base
8999
// allocator that does not free the memory (we leak it on purpose in order
90100
// to not free the memory used by _dl_fini() containing a map (array)
@@ -117,41 +127,28 @@ void proxy_lib_destroy_common(void) {
117127
Proxy_pool = NULL;
118128
umfPoolDestroy(pool);
119129
umfMemoryProviderDestroy(OS_memory_provider);
130+
ba_destroy();
120131
}
121132

122133
/*****************************************************************************/
123-
/*** The linear base allocator functions *************************************/
134+
/*** Generic version of realloc() of linear base allocator *******************/
124135
/*****************************************************************************/
125136

126-
static void proxy_lib_ba_init(void) { Base_alloc = umf_ba_linear_create(0); }
127-
128-
static inline void *ba_malloc(size_t size) {
129-
util_init_once(&Base_alloc_initialized, proxy_lib_ba_init);
130-
return umf_ba_linear_alloc(Base_alloc, size);
131-
}
132-
133-
static inline void *ba_calloc(size_t nmemb, size_t size) {
134-
util_init_once(&Base_alloc_initialized, proxy_lib_ba_init);
135-
// umf_ba_linear_alloc() returns zeroed memory
136-
return umf_ba_linear_alloc(Base_alloc, nmemb * size);
137-
}
138-
139-
static inline void *ba_realloc(void *ptr, size_t size) {
140-
util_init_once(&Base_alloc_initialized, proxy_lib_ba_init);
141-
137+
static void *ba_generic_realloc(umf_ba_linear_pool_t *pool, void *ptr,
138+
size_t size) {
142139
if (size == 0) {
143-
// it means free(ptr), but this BA does not free the memory
140+
// it means free(ptr), but linear base allocator does not implement free()
144141
return NULL;
145142
}
146143

147144
if (ptr == NULL) {
148-
return umf_ba_linear_alloc(Base_alloc, size);
145+
return umf_ba_linear_alloc(pool, size);
149146
}
150147

151-
size_t max_size = umf_ba_linear_pool_contains_pointer(Base_alloc, ptr);
148+
size_t max_size = umf_ba_linear_pool_contains_pointer(pool, ptr);
152149
assert(max_size > 0); // assert that pool contains the pointer
153150

154-
void *new_ptr = umf_ba_linear_alloc(Base_alloc, size);
151+
void *new_ptr = umf_ba_linear_alloc(pool, size);
155152
if (!new_ptr) {
156153
return NULL;
157154
}
@@ -165,42 +162,70 @@ static inline void *ba_realloc(void *ptr, size_t size) {
165162
return new_ptr;
166163
}
167164

168-
static inline void *ba_aligned_alloc(size_t alignment, size_t size) {
169-
util_init_once(&Base_alloc_initialized, proxy_lib_ba_init);
170-
void *ptr = umf_ba_linear_alloc(Base_alloc, size + alignment);
165+
/*****************************************************************************/
166+
/*** The LEAK linear base allocator functions ********************************/
167+
/*****************************************************************************/
168+
169+
static void ba_leak_create(void) { Base_alloc_leak = umf_ba_linear_create(0); }
170+
171+
// it does not implement destroy(), because it will not free memory at all
172+
173+
static inline void *ba_leak_malloc(size_t size) {
174+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
175+
return umf_ba_linear_alloc(Base_alloc_leak, size);
176+
}
177+
178+
static inline void *ba_leak_calloc(size_t nmemb, size_t size) {
179+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
180+
// umf_ba_linear_alloc() returns zeroed memory
181+
return umf_ba_linear_alloc(Base_alloc_leak, nmemb * size);
182+
}
183+
184+
static inline void *ba_leak_realloc(void *ptr, size_t size) {
185+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
186+
return ba_generic_realloc(Base_alloc_leak, ptr, size);
187+
}
188+
189+
static inline void *ba_leak_aligned_alloc(size_t alignment, size_t size) {
190+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
191+
void *ptr = umf_ba_linear_alloc(Base_alloc_leak, size + alignment);
171192
return (void *)ALIGN_UP((uintptr_t)ptr, alignment);
172193
}
173194

174195
/*****************************************************************************/
175-
/*** The system allocator functions ******************************************/
196+
/*** The second instance of linear base allocator functions ******************/
176197
/*****************************************************************************/
177198

178-
static inline void *system_malloc(size_t size) {
179-
util_init_once(&alloc_hooks_are_initialized, proxy_lib_system_alloc_init);
180-
return System_malloc_func(size);
199+
static void ba_create(void) {
200+
assert(Base_alloc == NULL);
201+
Base_alloc = umf_ba_linear_create(0);
202+
assert(Base_alloc);
181203
}
182204

183-
static inline void *system_calloc(size_t nmemb, size_t size) {
184-
util_init_once(&alloc_hooks_are_initialized, proxy_lib_system_alloc_init);
185-
return System_calloc_func(nmemb, size);
205+
static void ba_destroy(void) {
206+
if (Base_alloc) {
207+
umf_ba_linear_pool_t *pool = Base_alloc;
208+
Base_alloc = NULL;
209+
umf_ba_linear_destroy(pool);
210+
}
186211
}
187212

188-
static inline void *system_realloc(void *ptr, size_t size) {
189-
util_init_once(&alloc_hooks_are_initialized, proxy_lib_system_alloc_init);
190-
return System_realloc_func(ptr, size);
213+
static inline void *ba_malloc(size_t size) {
214+
return umf_ba_linear_alloc(Base_alloc, size);
191215
}
192216

193-
static inline void system_free(void *ptr) {
194-
util_init_once(&alloc_hooks_are_initialized, proxy_lib_system_alloc_init);
195-
System_free_func(ptr);
217+
static inline void *ba_calloc(size_t nmemb, size_t size) {
218+
// umf_ba_linear_alloc() returns zeroed memory
219+
return umf_ba_linear_alloc(Base_alloc, nmemb * size);
196220
}
197221

198-
static inline void *system_aligned_alloc(size_t alignment, size_t size) {
199-
util_init_once(&alloc_hooks_are_initialized, proxy_lib_system_alloc_init);
200-
if (!System_aligned_alloc_func) {
201-
return NULL; // unsupported
202-
}
203-
return System_aligned_alloc_func(alignment, size);
222+
static inline void *ba_realloc(void *ptr, size_t size) {
223+
return ba_generic_realloc(Base_alloc, ptr, size);
224+
}
225+
226+
static inline void *ba_aligned_alloc(size_t alignment, size_t size) {
227+
void *ptr = umf_ba_linear_alloc(Base_alloc, size + alignment);
228+
return (void *)ALIGN_UP((uintptr_t)ptr, alignment);
204229
}
205230

206231
/*****************************************************************************/
@@ -216,10 +241,10 @@ void *malloc(size_t size) {
216241
}
217242

218243
if (Constructors_started) {
219-
return system_malloc(size);
244+
return ba_malloc(size);
220245
}
221246

222-
return ba_malloc(size);
247+
return ba_leak_malloc(size);
223248
}
224249

225250
void *calloc(size_t nmemb, size_t size) {
@@ -231,10 +256,10 @@ void *calloc(size_t nmemb, size_t size) {
231256
}
232257

233258
if (Constructors_started) {
234-
return system_calloc(nmemb, size);
259+
return ba_calloc(nmemb, size);
235260
}
236261

237-
return ba_calloc(nmemb, size);
262+
return ba_leak_calloc(nmemb, size);
238263
}
239264

240265
void *realloc(void *ptr, size_t size) {
@@ -246,10 +271,10 @@ void *realloc(void *ptr, size_t size) {
246271
}
247272

248273
if (Constructors_started) {
249-
return system_realloc(ptr, size);
274+
return ba_realloc(ptr, size);
250275
}
251276

252-
return ba_realloc(ptr, size);
277+
return ba_leak_realloc(ptr, size);
253278
}
254279

255280
void free(void *ptr) {
@@ -267,9 +292,8 @@ void free(void *ptr) {
267292
return;
268293
}
269294

270-
if (Constructors_started) {
271-
system_free(ptr);
272-
}
295+
// 1) allocations from the second linear base allocator will be freed by ba_destroy().
296+
// 2) allocations from the leak linear base allocator will not be freed at all.
273297

274298
return;
275299
}
@@ -283,10 +307,10 @@ void *aligned_alloc(size_t alignment, size_t size) {
283307
}
284308

285309
if (Constructors_started) {
286-
return system_aligned_alloc(alignment, size);
310+
return ba_aligned_alloc(alignment, size);
287311
}
288312

289-
return ba_aligned_alloc(alignment, size);
313+
return ba_leak_aligned_alloc(alignment, size);
290314
}
291315

292316
size_t malloc_usable_size(void *ptr) {

src/proxy_lib/proxy_lib.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ extern aligned_alloc_func_t System_aligned_alloc_func;
2828

2929
void proxy_lib_create_common(void);
3030
void proxy_lib_destroy_common(void);
31-
void proxy_lib_system_alloc_init(void);
3231

3332
#ifdef __cplusplus
3433
}

src/proxy_lib/proxy_lib_linux.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,3 @@ void __attribute__((constructor(102))) proxy_lib_create(void) {
2727
void __attribute__((destructor(102))) proxy_lib_destroy(void) {
2828
proxy_lib_destroy_common();
2929
}
30-
31-
void proxy_lib_system_alloc_init(void) {
32-
// ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]
33-
*((void **)(&System_malloc_func)) = dlsym(RTLD_NEXT, "malloc");
34-
*((void **)(&System_calloc_func)) = dlsym(RTLD_NEXT, "calloc");
35-
*((void **)(&System_realloc_func)) = dlsym(RTLD_NEXT, "realloc");
36-
*((void **)(&System_free_func)) = dlsym(RTLD_NEXT, "free");
37-
*((void **)(&System_aligned_alloc_func)) =
38-
dlsym(RTLD_NEXT, "aligned_alloc");
39-
40-
// System_aligned_alloc_func can be NULL
41-
if (!System_malloc_func || !System_calloc_func || !System_realloc_func ||
42-
!System_free_func) {
43-
fprintf(stderr, "error: cannot find libc alloc functions\n");
44-
exit(-1);
45-
}
46-
}

src/proxy_lib/proxy_lib_windows.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,3 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
2525
}
2626
return TRUE;
2727
}
28-
29-
void proxy_lib_system_alloc_init(void) {
30-
/* there is a memleak here, we should unload this library in the destructor but there is no such thing */
31-
HMODULE mod = LoadLibrary(TEXT("msvcrt.dll"));
32-
33-
// ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]
34-
*((void **)(&System_malloc_func)) = GetProcAddress(mod, "malloc");
35-
*((void **)(&System_calloc_func)) = GetProcAddress(mod, "calloc");
36-
*((void **)(&System_realloc_func)) = GetProcAddress(mod, "realloc");
37-
*((void **)(&System_free_func)) = GetProcAddress(mod, "free");
38-
*((void **)(&System_aligned_alloc_func)) =
39-
GetProcAddress(mod, "aligned_alloc");
40-
41-
// System_aligned_alloc_func can be NULL
42-
if (!System_malloc_func || !System_calloc_func || !System_realloc_func ||
43-
!System_free_func) {
44-
fprintf(stderr, "error: cannot find libc alloc functions\n");
45-
exit(-1);
46-
}
47-
}

0 commit comments

Comments
 (0)