@@ -157,42 +157,50 @@ void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
157157}
158158#endif
159159
160-
161160/* -----------------------------------------------------------
162161 Free memory
163162-------------------------------------------------------------- */
164163
165164static void mi_os_free_huge_os_pages (void * p , size_t size );
166165
167- static void mi_os_prim_free (void * addr , size_t size , bool still_committed ) {
166+ static void mi_os_prim_free (void * addr , size_t size , size_t commit_size ) {
168167 mi_assert_internal ((size % _mi_os_page_size ()) == 0 );
169168 if (addr == NULL || size == 0 ) return ; // || _mi_os_is_huge_reserved(addr)
170169 int err = _mi_prim_free (addr , size );
171170 if (err != 0 ) {
172171 _mi_warning_message ("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n" , err , err , size , addr );
173172 }
174- if (still_committed ) { _mi_stat_decrease (& os_stats -> committed , size ); }
173+ if (commit_size > 0 ) {
174+ _mi_stat_decrease (& os_stats -> committed , commit_size );
175+ }
175176 _mi_stat_decrease (& os_stats -> reserved , size );
176177}
177178
178179void _mi_os_free_ex (void * addr , size_t size , bool still_committed , mi_memid_t memid ) {
179180 if (mi_memkind_is_os (memid .memkind )) {
180- size_t csize = _mi_os_good_alloc_size (size );
181+ size_t csize = memid .mem .os .size ;
182+ if (csize == 0 ) { _mi_os_good_alloc_size (size ); }
183+ size_t commit_size = (still_committed ? csize : 0 );
181184 void * base = addr ;
182185 // different base? (due to alignment)
183- if (memid .mem .os .base != NULL ) {
184- mi_assert (memid .mem .os .base <= addr );
185- mi_assert ((uint8_t * )memid .mem .os .base + memid .mem .os .alignment >= (uint8_t * )addr );
186+ if (memid .mem .os .base != base ) {
187+ mi_assert (memid .mem .os .base <= addr );
186188 base = memid .mem .os .base ;
187- csize += ((uint8_t * )addr - (uint8_t * )memid .mem .os .base );
189+ const size_t diff = (uint8_t * )addr - (uint8_t * )memid .mem .os .base ;
190+ if (memid .mem .os .size == 0 ) {
191+ csize += diff ;
192+ }
193+ if (still_committed ) {
194+ commit_size -= diff ; // the (addr-base) part was already un-committed
195+ }
188196 }
189197 // free it
190198 if (memid .memkind == MI_MEM_OS_HUGE ) {
191199 mi_assert (memid .is_pinned );
192200 mi_os_free_huge_os_pages (base , csize );
193201 }
194202 else {
195- mi_os_prim_free (base , csize , still_committed );
203+ mi_os_prim_free (base , csize , ( still_committed ? commit_size : 0 ) );
196204 }
197205 }
198206 else {
@@ -273,7 +281,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
273281 #if !MI_TRACK_ASAN
274282 _mi_warning_message ("unable to allocate aligned OS memory directly, fall back to over-allocation (size: 0x%zx bytes, address: %p, alignment: 0x%zx, commit: %d)\n" , size , p , alignment , commit );
275283 #endif
276- mi_os_prim_free (p , size , commit );
284+ if ( p != NULL ) { mi_os_prim_free (p , size , ( commit ? size : 0 )); }
277285 if (size >= (SIZE_MAX - alignment )) return NULL ; // overflow
278286 const size_t over_size = size + alignment ;
279287
@@ -304,8 +312,8 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
304312 size_t mid_size = _mi_align_up (size , _mi_os_page_size ());
305313 size_t post_size = over_size - pre_size - mid_size ;
306314 mi_assert_internal (pre_size < over_size && post_size < over_size && mid_size >= size );
307- if (pre_size > 0 ) { mi_os_prim_free (p , pre_size , commit ); }
308- if (post_size > 0 ) { mi_os_prim_free ((uint8_t * )aligned_p + mid_size , post_size , commit ); }
315+ if (pre_size > 0 ) { mi_os_prim_free (p , pre_size , ( commit ? pre_size : 0 ) ); }
316+ if (post_size > 0 ) { mi_os_prim_free ((uint8_t * )aligned_p + mid_size , post_size , ( commit ? post_size : 0 ) ); }
309317 // we can return the aligned pointer on `mmap` systems
310318 p = aligned_p ;
311319 * base = aligned_p ; // since we freed the pre part, `*base == p`.
@@ -446,8 +454,13 @@ bool _mi_os_commit(void* addr, size_t size, bool* is_zero) {
446454 return true;
447455}
448456
449- static bool mi_os_decommit_ex (void * addr , size_t size , bool * needs_recommit ) { mi_assert_internal (needs_recommit != NULL );
450- _mi_stat_decrease (& os_stats -> committed , size );
457+ bool _mi_os_commit (void * addr , size_t size , bool * is_zero ) {
458+ return _mi_os_commit_ex (addr , size , is_zero , size );
459+ }
460+
461+ static bool mi_os_decommit_ex (void * addr , size_t size , bool * needs_recommit , size_t stat_size ) {
462+ mi_assert_internal (needs_recommit != NULL );
463+ mi_os_stat_decrease (committed , stat_size );
451464
452465 // page align
453466 size_t csize ;
@@ -466,7 +479,7 @@ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit) {
466479
467480bool _mi_os_decommit (void * addr , size_t size ) {
468481 bool needs_recommit ;
469- return mi_os_decommit_ex (addr , size , & needs_recommit );
482+ return mi_os_decommit_ex (addr , size , & needs_recommit , size );
470483}
471484
472485
@@ -628,7 +641,7 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse
628641 // no success, issue a warning and break
629642 if (p != NULL ) {
630643 _mi_warning_message ("could not allocate contiguous huge OS page %zu at %p\n" , page , addr );
631- mi_os_prim_free (p , MI_HUGE_OS_PAGE_SIZE , true );
644+ mi_os_prim_free (p , MI_HUGE_OS_PAGE_SIZE , MI_HUGE_OS_PAGE_SIZE );
632645 }
633646 break ;
634647 }
@@ -674,7 +687,7 @@ static void mi_os_free_huge_os_pages(void* p, size_t size) {
674687 if (p == NULL || size == 0 ) return ;
675688 uint8_t * base = (uint8_t * )p ;
676689 while (size >= MI_HUGE_OS_PAGE_SIZE ) {
677- mi_os_prim_free (base , MI_HUGE_OS_PAGE_SIZE , true );
690+ mi_os_prim_free (base , MI_HUGE_OS_PAGE_SIZE , MI_HUGE_OS_PAGE_SIZE );
678691 size -= MI_HUGE_OS_PAGE_SIZE ;
679692 base += MI_HUGE_OS_PAGE_SIZE ;
680693 }
0 commit comments