ruby-changes:72697
From: Jemma <ko1@a...>
Date: Wed, 27 Jul 2022 01:40:05 +0900 (JST)
Subject: [ruby-changes:72697] 36d0c71ace (master): Refactored poisoning and unpoisoning freelist to simpler API
https://git.ruby-lang.org/ruby.git/commit/?id=36d0c71ace From 36d0c71acef5e80384c13f9b43419318d2127306 Mon Sep 17 00:00:00 2001 From: Jemma Issroff <jemmaissroff@g...> Date: Wed, 25 May 2022 10:17:04 -0400 Subject: Refactored poisoning and unpoisoning freelist to simpler API --- gc.c | 62 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/gc.c b/gc.c index a9961e92e7..24078afc5a 100644 --- a/gc.c +++ b/gc.c @@ -958,6 +958,24 @@ struct heap_page { https://github.com/ruby/ruby/blob/trunk/gc.c#L958 bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT]; }; +/* + * When asan is enabled, this will prohibit writing to the freelist until it is unlocked + */ +static void +asan_lock_freelist(struct heap_page *page) +{ + asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); +} + +/* + * When asan is enabled, this will enable the ability to write to the freelist + */ +static void +asan_unlock_freelist(struct heap_page *page) +{ + asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); +} + #define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_PAGE_ALIGN_MASK))) #define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header) #define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page) @@ -1939,12 +1957,12 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj https://github.com/ruby/ruby/blob/trunk/gc.c#L1957 asan_unpoison_object(obj, false); - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); p->as.free.flags = 0; p->as.free.next = page->freelist; page->freelist = p; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); if (RGENGC_CHECK_MODE && /* obj should belong to page */ @@ -1961,7 +1979,7 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj https://github.com/ruby/ruby/blob/trunk/gc.c#L1979 static inline void heap_add_freepage(rb_heap_t *heap, struct heap_page *page) { - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); GC_ASSERT(page->free_slots != 0); GC_ASSERT(page->freelist != NULL); @@ -1970,14 +1988,14 @@ heap_add_freepage(rb_heap_t *heap, struct heap_page *page) https://github.com/ruby/ruby/blob/trunk/gc.c#L1988 RUBY_DEBUG_LOG("page:%p freelist:%p", (void *)page, (void *)page->freelist); - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); } #if GC_ENABLE_INCREMENTAL_MARK static inline void heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page) { - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); GC_ASSERT(page->free_slots != 0); GC_ASSERT(page->freelist != NULL); @@ -1985,7 +2003,7 @@ heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pa https://github.com/ruby/ruby/blob/trunk/gc.c#L2003 heap->pooled_pages = page; objspace->rincgc.pooled_slots += page->free_slots; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); } #endif @@ -2209,7 +2227,7 @@ heap_page_allocate(rb_objspace_t *objspace, rb_size_pool_t *size_pool) https://github.com/ruby/ruby/blob/trunk/gc.c#L2227 } page->free_slots = limit; - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); return page; } @@ -2219,12 +2237,12 @@ heap_page_resurrect(rb_objspace_t *objspace, rb_size_pool_t *size_pool) https://github.com/ruby/ruby/blob/trunk/gc.c#L2237 struct heap_page *page = 0, *next; ccan_list_for_each_safe(&SIZE_POOL_TOMB_HEAP(size_pool)->pages, page, next, page_node) { - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - if (page->freelist != NULL) { - heap_unlink_page(objspace, &size_pool->tomb_heap, page); - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); - return page; - } + asan_unlock_freelist(page); + if (page->freelist != NULL) { + heap_unlink_page(objspace, &size_pool->tomb_heap, page); + asan_lock_freelist(page); + return page; + } } return NULL; @@ -2618,7 +2636,7 @@ heap_next_free_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_ https://github.com/ruby/ruby/blob/trunk/gc.c#L2636 GC_ASSERT(page->free_slots != 0); RUBY_DEBUG_LOG("page:%p freelist:%p cnt:%d", (void *)page, (void *)page->freelist, page->free_slots); - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); return page; } @@ -5659,13 +5677,13 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context https://github.com/ruby/ruby/blob/trunk/gc.c#L5677 #if RGENGC_CHECK_MODE short freelist_len = 0; - asan_unpoison_memory_region(&sweep_page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(sweep_page); RVALUE *ptr = sweep_page->freelist; while (ptr) { freelist_len++; ptr = ptr->as.free.next; } - asan_poison_memory_region(&sweep_page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(sweep_page); if (freelist_len != sweep_page->free_slots) { rb_bug("inconsistent freelist length: expected %d but was %d", sweep_page->free_slots, freelist_len); } @@ -5723,7 +5741,7 @@ static void https://github.com/ruby/ruby/blob/trunk/gc.c#L5741 heap_page_freelist_append(struct heap_page *page, RVALUE *freelist) { if (freelist) { - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); if (page->freelist) { RVALUE *p = page->freelist; asan_unpoison_object((VALUE)p, false); @@ -5739,7 +5757,7 @@ heap_page_freelist_append(struct heap_page *page, RVALUE *freelist) https://github.com/ruby/ruby/blob/trunk/gc.c#L5757 else { page->freelist = freelist; } - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); } } @@ -7934,7 +7952,7 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct ccan_list_head *head) https://github.com/ruby/ruby/blob/trunk/gc.c#L7952 struct heap_page *page = 0; ccan_list_for_each(head, page, page_node) { - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); + asan_unlock_freelist(page); RVALUE *p = page->freelist; while (p) { VALUE vp = (VALUE)p; @@ -7946,7 +7964,7 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct ccan_list_head *head) https://github.com/ruby/ruby/blob/trunk/gc.c#L7964 p = p->as.free.next; asan_poison_object(prev); } - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_lock_freelist(page); if (page->flags.has_remembered_objects == FALSE) { remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse); @@ -10582,8 +10600,8 @@ static int https://github.com/ruby/ruby/blob/trunk/gc.c#L10600 gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace, struct heap_page *page) { VALUE v = (VALUE)vstart; - asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); + asan_unlock_freelist(page); + asan_lock_freelist(page); page->flags.has_uncollectible_shady_objects = FALSE; page->flags.has_remembered_objects = FALSE; -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/