Skip to content

Commit 3d22cdc

Browse files
committed
perf improvements, code reduction, makefile cleanup
1 parent 06458cc commit 3d22cdc

4 files changed

Lines changed: 27 additions & 47 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ SANITIZER_SUPPORT = $(ENABLE_ASAN) $(ENABLE_MSAN) $(ENABLE_UBSAN) $(ENABLE_TSAN)
4646
## You can safely disable it here if you know your
4747
## program does not require concurrent access
4848
## to the IsoAlloc APIs
49-
THREAD_SUPPORT = -DTHREAD_SUPPORT=1
49+
THREAD_SUPPORT = -DTHREAD_SUPPORT=1 -pthread
5050

5151
## By default IsoAlloc uses a pthread mutex to synchronize
5252
## thread safe access to the root structure. By enabling this
@@ -189,7 +189,7 @@ endif
189189
CFLAGS = $(COMMON_CFLAGS) $(SECURITY_FLAGS) $(BUILD_ERROR_FLAGS) $(HOOKS) $(HEAP_PROFILER) -fvisibility=hidden \
190190
-std=c11 $(SANITIZER_SUPPORT) $(ALLOC_SANITY) $(UNINIT_READ_SANITY) $(CPU_PIN) $(EXPERIMENTAL) $(UAF_PTR_PAGE) \
191191
$(VERIFY_BIT_SLOT_CACHE) $(NAMED_MAPPINGS) $(ABORT_ON_NULL) $(NO_ZERO_ALLOCATIONS) $(ABORT_NO_ENTROPY) \
192-
$(ISO_DTOR_CLEANUP) $(SHUFFLE_BIT_SLOT_CACHE) $(USE_SPINLOCK) -pthread $(HUGE_PAGES) $(USE_MLOCK) $(MEMORY_TAGGING)
192+
$(ISO_DTOR_CLEANUP) $(SHUFFLE_BIT_SLOT_CACHE) $(USE_SPINLOCK) $(HUGE_PAGES) $(USE_MLOCK) $(MEMORY_TAGGING)
193193
CXXFLAGS = $(COMMON_CFLAGS) -DCPP_SUPPORT=1 -std=c++17 $(SANITIZER_SUPPORT) $(HOOKS)
194194
EXE_CFLAGS = -fPIE
195195
GDB_FLAGS = -g -ggdb3 -fno-omit-frame-pointer

include/iso_alloc_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ INTERNAL_HIDDEN INLINE void insert_free_bit_slot(iso_alloc_zone_t *zone, int64_t
518518
INTERNAL_HIDDEN INLINE void write_canary(iso_alloc_zone_t *zone, void *p);
519519
INTERNAL_HIDDEN INLINE void populate_zone_cache(iso_alloc_zone_t *zone);
520520
INTERNAL_HIDDEN INLINE void _flush_chunk_quarantine(void);
521-
INTERNAL_HIDDEN INLINE void clear_chunk_quarantine(void);
522521
INTERNAL_HIDDEN INLINE void clear_zone_cache(void);
523522
INTERNAL_HIDDEN iso_alloc_zone_t *is_zone_usable(iso_alloc_zone_t *zone, size_t size);
524523
INTERNAL_HIDDEN iso_alloc_zone_t *find_suitable_zone(size_t size);
@@ -552,6 +551,7 @@ INTERNAL_HIDDEN void _iso_free_size(void *p, size_t size);
552551
INTERNAL_HIDDEN void _iso_free_from_zone(void *p, iso_alloc_zone_t *zone, bool permanent);
553552
INTERNAL_HIDDEN void iso_free_big_zone(iso_alloc_big_zone_t *big_zone, bool permanent);
554553
INTERNAL_HIDDEN void _iso_alloc_protect_root(void);
554+
INTERNAL_HIDDEN void _iso_free_quarantine(void *p);
555555
INTERNAL_HIDDEN void _iso_alloc_unprotect_root(void);
556556
INTERNAL_HIDDEN void _unmap_zone(iso_alloc_zone_t *zone);
557557
INTERNAL_HIDDEN void *_tag_ptr(void *p, iso_alloc_zone_t *zone);

src/iso_alloc.c

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,26 @@ pthread_mutex_t root_busy_mutex;
1313
pthread_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 */
2022
static __thread _tzc zone_cache[ZONE_CACHE_SZ];
2123
static __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 */
2928
static _tzc *zone_cache;
3029
static 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 */
3234
static uintptr_t *chunk_quarantine;
3335
static size_t chunk_quarantine_count;
34-
#endif
3536

3637
uint32_t g_page_size;
3738
uint32_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

469471
INTERNAL_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-
18221808
INTERNAL_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

18761861
INTERNAL_HIDDEN void _iso_free_size(void *p, size_t size) {

tests/thread_tests.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ void run_test_threads() {
9797
pthread_create(&t, NULL, allocate, (void *) &ALLOC);
9898
pthread_create(&tt, NULL, allocate, (void *) &REALLOC);
9999
pthread_create(&ttt, NULL, allocate, (void *) &CALLOC);
100-
101-
pthread_join(t, NULL);
102-
pthread_join(tt, NULL);
103-
pthread_join(ttt, NULL);
104-
pthread_exit(NULL);
105100
#endif
106101
}
107102

0 commit comments

Comments
 (0)