@@ -13,25 +13,26 @@ pthread_mutex_t root_busy_mutex;
1313pthread_mutex_t big_zone_busy_mutex ;
1414#endif
1515
16- /* We cannot initialize these on thread creation so
16+ /* We cannot initialize this on thread creation so
1717 * we can't mmap them somewhere with guard pages but
1818 * they are thread local storage so their location
19- * won't be as predictable as .bss */
19+ * won't be as predictable as .bss
20+ * If a thread dies with the zone cache populated there
21+ * is no undefined behavior */
2022static __thread _tzc zone_cache [ZONE_CACHE_SZ ];
2123static __thread size_t zone_cache_count ;
22-
23- static __thread uintptr_t chunk_quarantine [CHUNK_QUARANTINE_SZ ];
24- static __thread size_t chunk_quarantine_count ;
2524#else
2625/* When not using thread local storage we can mmap
2726 * these pages somewhere safer than global memory
2827 * and surrounded by guard pages */
2928static _tzc * zone_cache ;
3029static size_t zone_cache_count ;
30+ #endif
3131
32+ /* The chunk quarantine is shared by each thread.
33+ * It is protected by the root lock */
3234static uintptr_t * chunk_quarantine ;
3335static size_t chunk_quarantine_count ;
34- #endif
3536
3637uint32_t g_page_size ;
3738uint32_t g_page_size_shift ;
@@ -382,14 +383,14 @@ INTERNAL_HIDDEN void iso_alloc_initialize_global_root(void) {
382383 name_mapping (p , _root -> zones_size , "isoalloc zone metadata" );
383384 MLOCK (_root -> zones , _root -> zones_size );
384385
385- #if !THREAD_SUPPORT
386386 size_t c = ROUND_UP_PAGE (CHUNK_QUARANTINE_SZ * sizeof (uintptr_t ));
387387 chunk_quarantine = mmap_rw_pages (c + (g_page_size * 2 ), true, NULL );
388388 create_guard_page (chunk_quarantine );
389389 chunk_quarantine = chunk_quarantine + (g_page_size / sizeof (uintptr_t ));
390390 create_guard_page ((void * ) chunk_quarantine + c );
391391 MLOCK (chunk_quarantine , c );
392392
393+ #if !THREAD_SUPPORT
393394 size_t z = ROUND_UP_PAGE (ZONE_CACHE_SZ * sizeof (_tzc ));
394395 zone_cache = mmap_rw_pages (z + (g_page_size + 2 ), true, NULL );
395396 create_guard_page (zone_cache );
@@ -463,12 +464,12 @@ INTERNAL_HIDDEN INLINE void _flush_chunk_quarantine() {
463464 _iso_free_internal_unlocked ((void * ) chunk_quarantine [i ], false, NULL );
464465 }
465466
466- clear_chunk_quarantine ();
467+ memset (chunk_quarantine , 0x0 , CHUNK_QUARANTINE_SZ * sizeof (uintptr_t ));
468+ chunk_quarantine_count = 0 ;
467469}
468470
469471INTERNAL_HIDDEN void _unmap_zone (iso_alloc_zone_t * zone ) {
470472 chunk_lookup_table [ADDR_TO_CHUNK_TABLE (zone -> user_pages_start )] = 0 ;
471-
472473 munmap (zone -> bitmap_start , zone -> bitmap_size );
473474 munmap (zone -> bitmap_start - _root -> system_page_size , _root -> system_page_size );
474475 munmap (zone -> bitmap_start + zone -> bitmap_size , _root -> system_page_size );
@@ -543,13 +544,12 @@ INTERNAL_HIDDEN void _iso_alloc_destroy_zone_unlocked(iso_alloc_zone_t *zone, bo
543544 madvise (zone -> user_pages_start , ZONE_USER_SIZE , MADV_DONTNEED );
544545 POISON_ZONE (zone );
545546 } else {
547+ _unmap_zone (zone );
548+
546549 if (replace == true) {
547550 /* The only time we ever destroy a non-private zone
548551 * is from the destructor so its safe unmap pages */
549- _unmap_zone (zone );
550552 _iso_new_zone (zone -> chunk_size , true, zone -> index );
551- } else {
552- _unmap_zone (zone );
553553 }
554554 }
555555}
@@ -630,12 +630,8 @@ __attribute__((destructor(LAST_DTOR))) void iso_alloc_dtor(void) {
630630 munmap (_root , sizeof (iso_alloc_root ));
631631 munmap (zone_lookup_table , ZONE_LOOKUP_TABLE_SZ );
632632 munmap (chunk_lookup_table , CHUNK_TO_ZONE_TABLE_SZ );
633-
634- #if !THREAD_SUPPORT
635633 munmap (chunk_quarantine - (g_page_size / sizeof (uintptr_t )), ROUND_UP_PAGE (CHUNK_QUARANTINE_SZ * sizeof (uintptr_t )) + (g_page_size * 2 ));
636634 munmap (zone_cache - g_page_size , ROUND_UP_PAGE (ZONE_CACHE_SZ * sizeof (_tzc )) + g_page_size * 2 );
637- #endif
638-
639635#endif
640636 UNLOCK_ROOT ();
641637}
@@ -680,7 +676,7 @@ INTERNAL_HIDDEN iso_alloc_zone_t *_iso_new_zone(size_t size, bool internal, int3
680676 iso_alloc_zone_t * new_zone = NULL ;
681677
682678 /* We created a new zone, we did not replace a retired one */
683- if (index > 0 ) {
679+ if (index >= 0 ) {
684680 new_zone = & _root -> zones [index ];
685681 } else {
686682 new_zone = & _root -> zones [_root -> zones_used ];
@@ -1809,16 +1805,6 @@ INTERNAL_HIDDEN void _iso_free_from_zone(void *p, iso_alloc_zone_t *zone, bool p
18091805 UNLOCK_ROOT ();
18101806}
18111807
1812- INTERNAL_HIDDEN INLINE void clear_chunk_quarantine () {
1813- #if THREAD_SUPPORT
1814- memset (chunk_quarantine , 0x0 , sizeof (chunk_quarantine ));
1815- #else
1816- memset (chunk_quarantine , 0x0 , CHUNK_QUARANTINE_SZ * sizeof (uintptr_t ));
1817- #endif
1818-
1819- chunk_quarantine_count = 0 ;
1820- }
1821-
18221808INTERNAL_HIDDEN INLINE void clear_zone_cache () {
18231809#if THREAD_SUPPORT
18241810 memset (zone_cache , 0x0 , sizeof (zone_cache ));
@@ -1857,20 +1843,19 @@ INTERNAL_HIDDEN void _iso_free(void *p, bool permanent) {
18571843 return ;
18581844 }
18591845
1860- if (chunk_quarantine_count < CHUNK_QUARANTINE_SZ ) {
1861- chunk_quarantine [chunk_quarantine_count ] = (uintptr_t ) p ;
1862- chunk_quarantine_count ++ ;
1863- return ;
1864- } else {
1865- for (int64_t i = 0 ; i < chunk_quarantine_count ; i ++ ) {
1866- _iso_free_internal ((void * ) chunk_quarantine [i ], false);
1867- }
1846+ LOCK_ROOT ();
18681847
1869- clear_chunk_quarantine ();
1870- chunk_quarantine [chunk_quarantine_count ] = (uintptr_t ) p ;
1871- chunk_quarantine_count ++ ;
1872- return ;
1848+ if (chunk_quarantine_count >= CHUNK_QUARANTINE_SZ ) {
1849+ /* If the quarantine is full that means we got the
1850+ * lock before our handle_quarantine_thread could.
1851+ * Flushing the quarantine has the same perf cost */
1852+ _flush_chunk_quarantine ();
18731853 }
1854+
1855+ chunk_quarantine [chunk_quarantine_count ] = (uintptr_t ) p ;
1856+ chunk_quarantine_count ++ ;
1857+
1858+ UNLOCK_ROOT ();
18741859}
18751860
18761861INTERNAL_HIDDEN void _iso_free_size (void * p , size_t size ) {
0 commit comments