fix, generalize, and speed up GC ownership check
This commit is contained in:
parent
ea3cabfc45
commit
6784007206
|
@ -48,7 +48,6 @@ intptr_t mp_ac_freed;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define POINTER_OWNERSHIP_CHECK
|
#define POINTER_OWNERSHIP_CHECK
|
||||||
#define LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MZ_PRECISE_GC /* required for mz includes to work right */
|
#define MZ_PRECISE_GC /* required for mz includes to work right */
|
||||||
|
@ -378,17 +377,67 @@ inline static void check_used_against_max(NewGC *gc, size_t len)
|
||||||
|
|
||||||
#include "vm.c"
|
#include "vm.c"
|
||||||
|
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
# define SHARED_PAGE_ORPHANED ((NewGC *)0x1)
|
||||||
|
static mzrt_mutex *lock;
|
||||||
|
static PageMap shared_pagemap;
|
||||||
|
inline static void pagemap_set(PageMap page_maps1, void *p, mpage *value);
|
||||||
|
inline static mpage *pagemap_find_page(PageMap page_maps1, const void *p);
|
||||||
|
void shared_pagemap_set(void *ptr, size_t len, NewGC *owner)
|
||||||
|
{
|
||||||
|
if (!lock) {
|
||||||
|
mzrt_mutex_create(&lock);
|
||||||
|
# ifdef SIXTY_FOUR_BIT_INTEGERS
|
||||||
|
shared_pagemap = ofm_malloc_zero(PAGEMAP64_LEVEL1_SIZE * sizeof (mpage***));
|
||||||
|
# else
|
||||||
|
shared_pagemap = ofm_malloc_zero(PAGEMAP32_SIZE * sizeof (mpage*));
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
mzrt_mutex_lock(lock);
|
||||||
|
while (len > 0) {
|
||||||
|
pagemap_set(shared_pagemap, ptr, (mpage*)owner);
|
||||||
|
len -= APAGE_SIZE;
|
||||||
|
ptr = (char *)ptr + APAGE_SIZE;
|
||||||
|
}
|
||||||
|
mzrt_mutex_unlock(lock);
|
||||||
|
}
|
||||||
|
void check_page_owner(NewGC *gc, const void *p)
|
||||||
|
{
|
||||||
|
NewGC *owner;
|
||||||
|
owner = (NewGC *)pagemap_find_page(shared_pagemap, p);
|
||||||
|
if (owner && (owner != gc) && (owner != MASTERGC) && (owner != SHARED_PAGE_ORPHANED)) {
|
||||||
|
mzrt_mutex_lock(lock);
|
||||||
|
owner = (NewGC *)pagemap_find_page(shared_pagemap, p);
|
||||||
|
if (owner && (owner != gc) && (owner != MASTERGC) && (owner != SHARED_PAGE_ORPHANED)) {
|
||||||
|
printf("%p is owned by place %i not the current place %i\n", p, owner->place_id, gc->place_id);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
mzrt_mutex_unlock(lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void *malloc_pages(NewGC *gc, size_t len, size_t alignment, int dirty, int type, int expect_mprotect, void **src_block)
|
static void *malloc_pages(NewGC *gc, size_t len, size_t alignment, int dirty, int type, int expect_mprotect, void **src_block)
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
check_used_against_max(gc, len);
|
check_used_against_max(gc, len);
|
||||||
ptr = mmu_alloc_page(gc->mmu, len, alignment, dirty, type, expect_mprotect, src_block);
|
ptr = mmu_alloc_page(gc->mmu, len, alignment, dirty, type, expect_mprotect, src_block);
|
||||||
if (!ptr) out_of_memory();
|
if (!ptr) out_of_memory();
|
||||||
|
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(ptr, len, gc);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_pages(NewGC *gc, void *p, size_t len, int type, int expect_mprotect, void **src_block)
|
static void free_pages(NewGC *gc, void *p, size_t len, int type, int expect_mprotect, void **src_block)
|
||||||
{
|
{
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(p, len, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
gc->used_pages -= size_to_apage_count(len);
|
gc->used_pages -= size_to_apage_count(len);
|
||||||
mmu_free_page(gc->mmu, p, len, type, expect_mprotect, src_block, 1);
|
mmu_free_page(gc->mmu, p, len, type, expect_mprotect, src_block, 1);
|
||||||
}
|
}
|
||||||
|
@ -403,6 +452,10 @@ static void check_excessive_free_pages(NewGC *gc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_orphaned_page(NewGC *gc, mpage *tmp) {
|
static void free_orphaned_page(NewGC *gc, mpage *tmp) {
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(tmp->addr, round_to_apage_size(tmp->size), NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* free_pages decrements gc->used_pages which is incorrect, since this is an orphaned page,
|
/* free_pages decrements gc->used_pages which is incorrect, since this is an orphaned page,
|
||||||
* so we use mmu_free_page directly */
|
* so we use mmu_free_page directly */
|
||||||
mmu_free_page(gc->mmu, tmp->addr, round_to_apage_size(tmp->size),
|
mmu_free_page(gc->mmu, tmp->addr, round_to_apage_size(tmp->size),
|
||||||
|
@ -423,6 +476,11 @@ static void orphan_page_accounting(NewGC *gc, size_t allocate_size) {
|
||||||
inline static void pagemap_add_with_size(PageMap pagemap, mpage *page, intptr_t size);
|
inline static void pagemap_add_with_size(PageMap pagemap, mpage *page, intptr_t size);
|
||||||
static void adopt_page_accounting(NewGC *gc, mpage* tmp) {
|
static void adopt_page_accounting(NewGC *gc, mpage* tmp) {
|
||||||
size_t realpagesize = real_page_size(tmp);
|
size_t realpagesize = real_page_size(tmp);
|
||||||
|
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(tmp->addr, realpagesize, gc);
|
||||||
|
#endif
|
||||||
|
|
||||||
pagemap_add_with_size(gc->page_maps, tmp, realpagesize);
|
pagemap_add_with_size(gc->page_maps, tmp, realpagesize);
|
||||||
mmu_memory_allocated_inc(gc->mmu, realpagesize);
|
mmu_memory_allocated_inc(gc->mmu, realpagesize);
|
||||||
gc->used_pages += size_to_apage_count(realpagesize);
|
gc->used_pages += size_to_apage_count(realpagesize);
|
||||||
|
@ -480,10 +538,6 @@ inline static void free_page_maps(PageMap page_maps1) {
|
||||||
/* the page map makes a nice mapping from addresses to pages, allowing
|
/* the page map makes a nice mapping from addresses to pages, allowing
|
||||||
fairly fast lookup. this is useful. */
|
fairly fast lookup. this is useful. */
|
||||||
inline static void pagemap_set(PageMap page_maps1, void *p, mpage *value) {
|
inline static void pagemap_set(PageMap page_maps1, void *p, mpage *value) {
|
||||||
#ifdef LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
NewGC *gc = GC_get_GC();
|
|
||||||
mzrt_mutex_lock(gc->pagetable_lock);
|
|
||||||
#endif
|
|
||||||
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
||||||
uintptr_t pos;
|
uintptr_t pos;
|
||||||
mpage ***page_maps2;
|
mpage ***page_maps2;
|
||||||
|
@ -505,34 +559,9 @@ inline static void pagemap_set(PageMap page_maps1, void *p, mpage *value) {
|
||||||
#else
|
#else
|
||||||
page_maps1[PAGEMAP32_BITS(p)] = value;
|
page_maps1[PAGEMAP32_BITS(p)] = value;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
mzrt_mutex_unlock(gc->pagetable_lock);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static mpage *pagemap_find_page(PageMap page_maps1, const void *p) {
|
inline static mpage *pagemap_find_page(PageMap page_maps1, const void *p) {
|
||||||
#ifdef LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
|
|
||||||
mpage *result = NULL;
|
|
||||||
NewGC *gc = GC_get_GC();
|
|
||||||
mzrt_mutex_lock(gc->pagetable_lock);
|
|
||||||
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
|
||||||
mpage ***page_maps2;
|
|
||||||
mpage **page_maps3;
|
|
||||||
|
|
||||||
page_maps2 = page_maps1[PAGEMAP64_LEVEL1_BITS(p)];
|
|
||||||
if (!page_maps2) goto done;
|
|
||||||
page_maps3 = page_maps2[PAGEMAP64_LEVEL2_BITS(p)];
|
|
||||||
if (!page_maps3) goto done;
|
|
||||||
result = page_maps3[PAGEMAP64_LEVEL3_BITS(p)];
|
|
||||||
done:
|
|
||||||
#else
|
|
||||||
result = page_maps1[PAGEMAP32_BITS(p)];
|
|
||||||
#endif
|
|
||||||
mzrt_mutex_unlock(gc->pagetable_lock);
|
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
||||||
mpage ***page_maps2;
|
mpage ***page_maps2;
|
||||||
mpage **page_maps3;
|
mpage **page_maps3;
|
||||||
|
@ -545,8 +574,6 @@ inline static mpage *pagemap_find_page(PageMap page_maps1, const void *p) {
|
||||||
#else
|
#else
|
||||||
return page_maps1[PAGEMAP32_BITS(p)];
|
return page_maps1[PAGEMAP32_BITS(p)];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -958,6 +985,9 @@ static void *allocate_big(const size_t request_size_bytes, int type)
|
||||||
page is going to be sent to a different place, so don't account
|
page is going to be sent to a different place, so don't account
|
||||||
for it here, and don't put it in the page_map */
|
for it here, and don't put it in the page_map */
|
||||||
orphan_page_accounting(gc, allocate_size);
|
orphan_page_accounting(gc, allocate_size);
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(bpage->addr, round_to_apage_size(allocate_size), SHARED_PAGE_ORPHANED);
|
||||||
|
#endif
|
||||||
} else
|
} else
|
||||||
pagemap_add(gc->page_maps, bpage);
|
pagemap_add(gc->page_maps, bpage);
|
||||||
|
|
||||||
|
@ -994,9 +1024,12 @@ inline static mpage *create_new_medium_page(NewGC *gc, const int sz, const int p
|
||||||
gc->med_pages[pos] = page;
|
gc->med_pages[pos] = page;
|
||||||
gc->med_freelist_pages[pos] = page;
|
gc->med_freelist_pages[pos] = page;
|
||||||
|
|
||||||
if (gc->saved_allocator) /* see MESSAGE ALLOCATION above */
|
if (gc->saved_allocator) { /* see MESSAGE ALLOCATION above */
|
||||||
orphan_page_accounting(gc, APAGE_SIZE);
|
orphan_page_accounting(gc, APAGE_SIZE);
|
||||||
else
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(page->addr, APAGE_SIZE, SHARED_PAGE_ORPHANED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
pagemap_add(gc->page_maps, page);
|
pagemap_add(gc->page_maps, page);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
|
@ -1105,9 +1138,12 @@ inline static mpage *gen0_create_new_nursery_mpage(NewGC *gc, const size_t page_
|
||||||
page->size = PREFIX_SIZE;
|
page->size = PREFIX_SIZE;
|
||||||
GEN0_ALLOC_SIZE(page) = page_size;
|
GEN0_ALLOC_SIZE(page) = page_size;
|
||||||
|
|
||||||
if (gc->saved_allocator) /* see MESSAGE ALLOCATION above */
|
if (gc->saved_allocator) { /* see MESSAGE ALLOCATION above */
|
||||||
orphan_page_accounting(gc, page_size);
|
orphan_page_accounting(gc, page_size);
|
||||||
else
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
shared_pagemap_set(page->addr, page_size, SHARED_PAGE_ORPHANED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
pagemap_add_with_size(gc->page_maps, page, page_size);
|
pagemap_add_with_size(gc->page_maps, page, page_size);
|
||||||
|
|
||||||
GCVERBOSEPAGE(gc, "NEW gen0", page);
|
GCVERBOSEPAGE(gc, "NEW gen0", page);
|
||||||
|
@ -2417,9 +2453,6 @@ static void NewGCMasterInfo_initialize() {
|
||||||
MASTERGCINFO->alive = 0;
|
MASTERGCINFO->alive = 0;
|
||||||
MASTERGCINFO->ready = 0;
|
MASTERGCINFO->ready = 0;
|
||||||
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
|
||||||
MASTERGCINFO->places_gcs = ofm_malloc_zero(sizeof(NewGC*) * MASTERGCINFO->size);
|
|
||||||
#endif
|
|
||||||
for (i=0; i < 32; i++ ) {
|
for (i=0; i < 32; i++ ) {
|
||||||
MASTERGCINFO->signal_fds[i] = (void *)REAPED_SLOT_AVAILABLE;
|
MASTERGCINFO->signal_fds[i] = (void *)REAPED_SLOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -2564,9 +2597,6 @@ static intptr_t NewGCMasterInfo_find_free_id() {
|
||||||
MASTERGCINFO->size++;
|
MASTERGCINFO->size++;
|
||||||
MASTERGCINFO->alive++;
|
MASTERGCINFO->alive++;
|
||||||
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
|
||||||
MASTERGCINFO->places_gcs= realloc(MASTERGCINFO->places_gcs, sizeof(NewGC*) * MASTERGCINFO->size);
|
|
||||||
#endif
|
|
||||||
return MASTERGCINFO->size - 1;
|
return MASTERGCINFO->size - 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2590,9 +2620,6 @@ static void NewGCMasterInfo_register_gc(NewGC *newgc) {
|
||||||
intptr_t newid = NewGCMasterInfo_find_free_id();
|
intptr_t newid = NewGCMasterInfo_find_free_id();
|
||||||
newgc->place_id = newid;
|
newgc->place_id = newid;
|
||||||
MASTERGCINFO->signal_fds[newid] = (void *) CREATED_BUT_NOT_REGISTERED;
|
MASTERGCINFO->signal_fds[newid] = (void *) CREATED_BUT_NOT_REGISTERED;
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
|
||||||
MASTERGCINFO->places_gcs[newid] = newgc;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
GC_LOCK_DEBUG("UNMGCLOCK NewGCMasterInfo_register_gc\n");
|
GC_LOCK_DEBUG("UNMGCLOCK NewGCMasterInfo_register_gc\n");
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
|
@ -2665,9 +2692,6 @@ static NewGC *init_type_tags_worker(NewGC *inheritgc, NewGC *parentgc,
|
||||||
NewGC *gc;
|
NewGC *gc;
|
||||||
|
|
||||||
gc = ofm_malloc_zero(sizeof(NewGC));
|
gc = ofm_malloc_zero(sizeof(NewGC));
|
||||||
#ifdef LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
mzrt_mutex_create(&gc->pagetable_lock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* NOTE sets the constructed GC as the new Thread Specific GC. */
|
/* NOTE sets the constructed GC as the new Thread Specific GC. */
|
||||||
GC_set_GC(gc);
|
GC_set_GC(gc);
|
||||||
|
@ -2742,9 +2766,6 @@ void GC_destruct_child_gc() {
|
||||||
waiting = MASTERGC->major_places_gc;
|
waiting = MASTERGC->major_places_gc;
|
||||||
if (!waiting) {
|
if (!waiting) {
|
||||||
MASTERGCINFO->signal_fds[gc->place_id] = (void *) REAPED_SLOT_AVAILABLE;
|
MASTERGCINFO->signal_fds[gc->place_id] = (void *) REAPED_SLOT_AVAILABLE;
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
|
||||||
MASTERGCINFO->places_gcs[gc->place_id] = NULL;
|
|
||||||
#endif
|
|
||||||
gc->place_id = -1;
|
gc->place_id = -1;
|
||||||
MASTERGCINFO->alive--;
|
MASTERGCINFO->alive--;
|
||||||
}
|
}
|
||||||
|
@ -2964,23 +2985,7 @@ void GC_mark2(const void *const_p, struct NewGC *gc)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
check_page_owner(gc, p);
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int size = MASTERGCINFO->size;
|
|
||||||
for (i = 1; i < size; i++) {
|
|
||||||
if (gc->place_id != i
|
|
||||||
&& MASTERGCINFO->signal_fds[i] != (void*) REAPED_SLOT_AVAILABLE
|
|
||||||
&& MASTERGCINFO->signal_fds[i] != (void*) CREATED_BUT_NOT_REGISTERED
|
|
||||||
&& MASTERGCINFO->signal_fds[i] != (void*) SIGNALED_BUT_NOT_REGISTERED) {
|
|
||||||
if((page = pagemap_find_page(MASTERGCINFO->places_gcs[i]->page_maps, p))) {
|
|
||||||
printf("%p is owned by place %i not the current place %i\n", p, i, gc->place_id);
|
|
||||||
asm("int3");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
|
||||||
#endif
|
#endif
|
||||||
GCDEBUG((DEBUGOUTF,"Not marking %p (no page)\n",p));
|
GCDEBUG((DEBUGOUTF,"Not marking %p (no page)\n",p));
|
||||||
return;
|
return;
|
||||||
|
@ -3319,7 +3324,12 @@ void GC_fixup2(void *pp, struct NewGC *gc)
|
||||||
if(info->mark && info->moved)
|
if(info->mark && info->moved)
|
||||||
*(void**)pp = *(void**)p;
|
*(void**)pp = *(void**)p;
|
||||||
else GCDEBUG((DEBUGOUTF, "Not repairing %p from %p (not moved)\n",p,pp));
|
else GCDEBUG((DEBUGOUTF, "Not repairing %p from %p (not moved)\n",p,pp));
|
||||||
} else GCDEBUG((DEBUGOUTF, "Not repairing %p from %p (no page)\n", p, pp));
|
} else {
|
||||||
|
#ifdef POINTER_OWNERSHIP_CHECK
|
||||||
|
check_page_owner(gc, p);
|
||||||
|
#endif
|
||||||
|
GCDEBUG((DEBUGOUTF, "Not repairing %p from %p (no page)\n", p, pp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_fixup(void *pp)
|
void GC_fixup(void *pp)
|
||||||
|
|
|
@ -119,9 +119,6 @@ typedef struct NewGCMasterInfo {
|
||||||
uintptr_t alive;
|
uintptr_t alive;
|
||||||
uintptr_t ready;
|
uintptr_t ready;
|
||||||
void **signal_fds;
|
void **signal_fds;
|
||||||
#ifdef POINTER_OWNERSHIP_CHECK
|
|
||||||
struct NewGC **places_gcs;
|
|
||||||
#endif
|
|
||||||
mzrt_rwlock *cangc;
|
mzrt_rwlock *cangc;
|
||||||
mzrt_sema *wait_sema;
|
mzrt_sema *wait_sema;
|
||||||
} NewGCMasterInfo;
|
} NewGCMasterInfo;
|
||||||
|
@ -140,9 +137,6 @@ typedef struct NewGC {
|
||||||
Mark2_Proc *mark_table; /* the table of mark procs */
|
Mark2_Proc *mark_table; /* the table of mark procs */
|
||||||
Fixup2_Proc *fixup_table; /* the table of repair procs */
|
Fixup2_Proc *fixup_table; /* the table of repair procs */
|
||||||
PageMap page_maps;
|
PageMap page_maps;
|
||||||
#ifdef LOCK_PAGE_TABLES_FOR_DEBUG
|
|
||||||
mzrt_mutex *pagetable_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* All non-gen0 pages are held in the following structure. */
|
/* All non-gen0 pages are held in the following structure. */
|
||||||
struct mpage *gen1_pages[PAGE_TYPES];
|
struct mpage *gen1_pages[PAGE_TYPES];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user