Skip to content

Commit 8d15fb9

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

File tree

4 files changed

+89
-121
lines changed

4 files changed

+89
-121
lines changed

src/proxy_lib/proxy_lib.c

Lines changed: 89 additions & 71 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;
@@ -74,17 +78,17 @@ static umf_memory_pool_handle_t Proxy_pool = NULL;
7478
// it protects us from recursion in umfPool*()
7579
static __TLS int was_called_from_umfPool = 0;
7680

77-
malloc_func_t System_malloc_func;
78-
calloc_func_t System_calloc_func;
79-
realloc_func_t System_realloc_func;
80-
free_func_t System_free_func;
81-
aligned_alloc_func_t System_aligned_alloc_func;
82-
8381
/*****************************************************************************/
8482
/*** The constructor and destructor of the proxy library *********************/
8583
/*****************************************************************************/
8684

85+
static void ba_create(void);
86+
static void ba_destroy(void);
87+
8788
void proxy_lib_create_common(void) {
89+
// create the second instance of linear base allocator
90+
ba_create();
91+
8892
// The constructors of libraries were started. Stop using the linear base
8993
// allocator that does not free the memory (we leak it on purpose in order
9094
// to not free the memory used by _dl_fini() containing a map (array)
@@ -117,41 +121,28 @@ void proxy_lib_destroy_common(void) {
117121
Proxy_pool = NULL;
118122
umfPoolDestroy(pool);
119123
umfMemoryProviderDestroy(OS_memory_provider);
124+
ba_destroy();
120125
}
121126

122127
/*****************************************************************************/
123-
/*** The linear base allocator functions *************************************/
128+
/*** Generic version of realloc() of linear base allocator *******************/
124129
/*****************************************************************************/
125130

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-
131+
static void *ba_generic_realloc(umf_ba_linear_pool_t *pool, void *ptr,
132+
size_t size) {
142133
if (size == 0) {
143-
// it means free(ptr), but this BA does not free the memory
134+
// it means free(ptr), but linear base allocator does not implement free()
144135
return NULL;
145136
}
146137

147138
if (ptr == NULL) {
148-
return umf_ba_linear_alloc(Base_alloc, size);
139+
return umf_ba_linear_alloc(pool, size);
149140
}
150141

151-
size_t max_size = umf_ba_linear_pool_contains_pointer(Base_alloc, ptr);
142+
size_t max_size = umf_ba_linear_pool_contains_pointer(pool, ptr);
152143
assert(max_size > 0); // assert that pool contains the pointer
153144

154-
void *new_ptr = umf_ba_linear_alloc(Base_alloc, size);
145+
void *new_ptr = umf_ba_linear_alloc(pool, size);
155146
if (!new_ptr) {
156147
return NULL;
157148
}
@@ -165,42 +156,70 @@ static inline void *ba_realloc(void *ptr, size_t size) {
165156
return new_ptr;
166157
}
167158

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);
159+
/*****************************************************************************/
160+
/*** The LEAK linear base allocator functions ********************************/
161+
/*****************************************************************************/
162+
163+
static void ba_leak_create(void) { Base_alloc_leak = umf_ba_linear_create(0); }
164+
165+
// it does not implement destroy(), because it will not free memory at all
166+
167+
static inline void *ba_leak_malloc(size_t size) {
168+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
169+
return umf_ba_linear_alloc(Base_alloc_leak, size);
170+
}
171+
172+
static inline void *ba_leak_calloc(size_t nmemb, size_t size) {
173+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
174+
// umf_ba_linear_alloc() returns zeroed memory
175+
return umf_ba_linear_alloc(Base_alloc_leak, nmemb * size);
176+
}
177+
178+
static inline void *ba_leak_realloc(void *ptr, size_t size) {
179+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
180+
return ba_generic_realloc(Base_alloc_leak, ptr, size);
181+
}
182+
183+
static inline void *ba_leak_aligned_alloc(size_t alignment, size_t size) {
184+
util_init_once(&Base_alloc_leak_initialized, ba_leak_create);
185+
void *ptr = umf_ba_linear_alloc(Base_alloc_leak, size + alignment);
171186
return (void *)ALIGN_UP((uintptr_t)ptr, alignment);
172187
}
173188

174189
/*****************************************************************************/
175-
/*** The system allocator functions ******************************************/
190+
/*** The second instance of linear base allocator functions ******************/
176191
/*****************************************************************************/
177192

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);
193+
static void ba_create(void) {
194+
assert(Base_alloc == NULL);
195+
Base_alloc = umf_ba_linear_create(0);
196+
assert(Base_alloc);
181197
}
182198

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);
199+
static void ba_destroy(void) {
200+
if (Base_alloc) {
201+
umf_ba_linear_pool_t *pool = Base_alloc;
202+
Base_alloc = NULL;
203+
umf_ba_linear_destroy(pool);
204+
}
205+
}
206+
207+
static inline void *ba_malloc(size_t size) {
208+
return umf_ba_linear_alloc(Base_alloc, size);
186209
}
187210

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);
211+
static inline void *ba_calloc(size_t nmemb, size_t size) {
212+
// umf_ba_linear_alloc() returns zeroed memory
213+
return umf_ba_linear_alloc(Base_alloc, nmemb * size);
191214
}
192215

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);
216+
static inline void *ba_realloc(void *ptr, size_t size) {
217+
return ba_generic_realloc(Base_alloc, ptr, size);
196218
}
197219

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);
220+
static inline void *ba_aligned_alloc(size_t alignment, size_t size) {
221+
void *ptr = umf_ba_linear_alloc(Base_alloc, size + alignment);
222+
return (void *)ALIGN_UP((uintptr_t)ptr, alignment);
204223
}
205224

206225
/*****************************************************************************/
@@ -216,10 +235,10 @@ void *malloc(size_t size) {
216235
}
217236

218237
if (Constructors_started) {
219-
return system_malloc(size);
238+
return ba_malloc(size);
220239
}
221240

222-
return ba_malloc(size);
241+
return ba_leak_malloc(size);
223242
}
224243

225244
void *calloc(size_t nmemb, size_t size) {
@@ -231,10 +250,10 @@ void *calloc(size_t nmemb, size_t size) {
231250
}
232251

233252
if (Constructors_started) {
234-
return system_calloc(nmemb, size);
253+
return ba_calloc(nmemb, size);
235254
}
236255

237-
return ba_calloc(nmemb, size);
256+
return ba_leak_calloc(nmemb, size);
238257
}
239258

240259
void *realloc(void *ptr, size_t size) {
@@ -246,10 +265,10 @@ void *realloc(void *ptr, size_t size) {
246265
}
247266

248267
if (Constructors_started) {
249-
return system_realloc(ptr, size);
268+
return ba_realloc(ptr, size);
250269
}
251270

252-
return ba_realloc(ptr, size);
271+
return ba_leak_realloc(ptr, size);
253272
}
254273

255274
void free(void *ptr) {
@@ -267,9 +286,8 @@ void free(void *ptr) {
267286
return;
268287
}
269288

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

274292
return;
275293
}
@@ -283,10 +301,10 @@ void *aligned_alloc(size_t alignment, size_t size) {
283301
}
284302

285303
if (Constructors_started) {
286-
return system_aligned_alloc(alignment, size);
304+
return ba_aligned_alloc(alignment, size);
287305
}
288306

289-
return ba_aligned_alloc(alignment, size);
307+
return ba_leak_aligned_alloc(alignment, size);
290308
}
291309

292310
size_t malloc_usable_size(void *ptr) {

src/proxy_lib/proxy_lib.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,8 @@
1414
extern "C" {
1515
#endif
1616

17-
typedef void *(*malloc_func_t)(size_t size);
18-
typedef void *(*calloc_func_t)(size_t nmemb, size_t size);
19-
typedef void *(*realloc_func_t)(void *ptr, size_t size);
20-
typedef void (*free_func_t)(void *ptr);
21-
typedef void *(*aligned_alloc_func_t)(size_t alignment, size_t size);
22-
23-
extern malloc_func_t System_malloc_func;
24-
extern calloc_func_t System_calloc_func;
25-
extern realloc_func_t System_realloc_func;
26-
extern free_func_t System_free_func;
27-
extern aligned_alloc_func_t System_aligned_alloc_func;
28-
2917
void proxy_lib_create_common(void);
3018
void proxy_lib_destroy_common(void);
31-
void proxy_lib_system_alloc_init(void);
3219

3320
#ifdef __cplusplus
3421
}

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)