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.
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 ;
6973static umf_ba_linear_pool_t * Base_alloc = NULL ;
7074static int Constructors_started = 0 ;
7175static 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*()
7579static __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+
8788void 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
225244void * 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
240259void * 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
255274void 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
292310size_t malloc_usable_size (void * ptr ) {
0 commit comments