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 ;
@@ -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+
8794void 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
225250void * 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
240265void * 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
255280void 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
292316size_t malloc_usable_size (void * ptr ) {
0 commit comments