Places: prevent mastergc gen0.big_pages from leaking onto a places gen0.big_pages list
This commit is contained in:
parent
9a31ac5363
commit
57bda136ea
45
collects/tests/racket/benchmarks/places/place-channel.rktl
Normal file
45
collects/tests/racket/benchmarks/places/place-channel.rktl
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#lang racket
|
||||||
|
;; stress tests for place-channels
|
||||||
|
|
||||||
|
|
||||||
|
(define (splat txt fn)
|
||||||
|
(call-with-output-file fn #:exists 'replace
|
||||||
|
(lambda (out)
|
||||||
|
(fprintf out "~a" txt))))
|
||||||
|
|
||||||
|
(splat
|
||||||
|
#<<END
|
||||||
|
(module pct1 scheme
|
||||||
|
(provide place-main)
|
||||||
|
|
||||||
|
(define (place-main ch)
|
||||||
|
(define message-size (* 4024 1024))
|
||||||
|
(define count 500)
|
||||||
|
(define fourk-b-message (make-bytes message-size 66))
|
||||||
|
(for ([i (in-range count)])
|
||||||
|
(place-channel-recv ch)
|
||||||
|
(place-channel-send ch fourk-b-message)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
END
|
||||||
|
"pct1.ss")
|
||||||
|
|
||||||
|
(let ([pl (place "pct1.ss" 'place-main)])
|
||||||
|
(define message-size (* 4024 1024))
|
||||||
|
(define four-k-message (make-bytes message-size 65))
|
||||||
|
(define count 500)
|
||||||
|
(define-values (r t1 t2 t3)
|
||||||
|
(time-apply (lambda ()
|
||||||
|
(for ([i (in-range count)])
|
||||||
|
(place-channel-send pl four-k-message)
|
||||||
|
(place-channel-recv pl)
|
||||||
|
)) null))
|
||||||
|
|
||||||
|
|
||||||
|
(define B/sE (/ (* 2 count message-size) (/ t2 1000)))
|
||||||
|
(printf "~a ~a ~a ~a~n" r t1 t2 t3)
|
||||||
|
(printf "B/s ~a~n" (exact->inexact B/sE))
|
||||||
|
(printf "MB/s ~a~n" (exact->inexact (/ B/sE (* 1024 1024))))
|
||||||
|
(place-wait pl)
|
||||||
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GCLIST_H
|
#ifndef GCLIST_H
|
||||||
#define GCLIST_H
|
#define GCLIST_H
|
||||||
|
|
||||||
/* design take form the linux double linked list implementation in include/linux/list.h */
|
/* design taken from the linux double linked list implementation in include/linux/list.h */
|
||||||
|
|
||||||
typedef struct GCList {
|
typedef struct GCList {
|
||||||
struct GCList *next;
|
struct GCList *next;
|
||||||
|
|
|
@ -656,6 +656,12 @@ static size_t round_to_apage_size(size_t sizeb)
|
||||||
return sizeb;
|
return sizeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static inline size_t size_in_apages(mpage *page) {
|
||||||
|
return (page->size_class > 1) ? (round_to_apage_size(page->size) / APAGE_SIZE) : 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static mpage *malloc_mpage()
|
static mpage *malloc_mpage()
|
||||||
{
|
{
|
||||||
mpage *page;
|
mpage *page;
|
||||||
|
@ -2467,6 +2473,31 @@ long GC_get_memory_use(void *o)
|
||||||
/* Garbage collection proper ... and all the mess therein */
|
/* Garbage collection proper ... and all the mess therein */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void promote_marked_gen0_big_page(NewGC *gc, mpage *page) {
|
||||||
|
page->generation = 1;
|
||||||
|
|
||||||
|
/* remove page */
|
||||||
|
if(page->prev) page->prev->next = page->next; else
|
||||||
|
gc->gen0.big_pages = page->next;
|
||||||
|
if(page->next) page->next->prev = page->prev;
|
||||||
|
|
||||||
|
GCVERBOSEPAGE(gc, "MOVING BIG PAGE TO GEN1", page);
|
||||||
|
|
||||||
|
backtrace_new_page(gc, page);
|
||||||
|
|
||||||
|
/* add to gen1 */
|
||||||
|
page->next = gc->gen1_pages[PAGE_BIG];
|
||||||
|
page->prev = NULL;
|
||||||
|
if(page->next) page->next->prev = page;
|
||||||
|
gc->gen1_pages[PAGE_BIG] = page;
|
||||||
|
|
||||||
|
/* if we're doing memory accounting, then we need to make sure the
|
||||||
|
btc_mark is right */
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_set_btc_mark(gc, BIG_PAGE_TO_OBJHEAD(page));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* We use two mark routines to handle propagation. Why two? The first is the
|
/* We use two mark routines to handle propagation. Why two? The first is the
|
||||||
one that we export out, and it does a metric crapload of work. The second
|
one that we export out, and it does a metric crapload of work. The second
|
||||||
we use internally, and it doesn't do nearly as much. */
|
we use internally, and it doesn't do nearly as much. */
|
||||||
|
@ -2474,6 +2505,9 @@ long GC_get_memory_use(void *o)
|
||||||
/* This is the first mark routine. It's a bit complicated. */
|
/* This is the first mark routine. It's a bit complicated. */
|
||||||
void GC_mark2(const void *const_p, struct NewGC *gc)
|
void GC_mark2(const void *const_p, struct NewGC *gc)
|
||||||
{
|
{
|
||||||
|
#ifdef MZ_USE_PLACES
|
||||||
|
int is_a_master_page = 0;
|
||||||
|
#endif
|
||||||
mpage *page;
|
mpage *page;
|
||||||
void *p = (void*)const_p;
|
void *p = (void*)const_p;
|
||||||
|
|
||||||
|
@ -2490,6 +2524,11 @@ void GC_mark2(const void *const_p, struct NewGC *gc)
|
||||||
GCDEBUG((DEBUGOUTF,"Not marking %p (no page)\n",p));
|
GCDEBUG((DEBUGOUTF,"Not marking %p (no page)\n",p));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef MZ_USE_PLACES
|
||||||
|
else {
|
||||||
|
is_a_master_page = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* toss this over to the BTC mark routine if we're doing accounting */
|
/* toss this over to the BTC mark routine if we're doing accounting */
|
||||||
|
@ -2513,29 +2552,13 @@ void GC_mark2(const void *const_p, struct NewGC *gc)
|
||||||
page->size_class = 3;
|
page->size_class = 3;
|
||||||
|
|
||||||
/* if this is in the nursery, we want to move it out of the nursery */
|
/* if this is in the nursery, we want to move it out of the nursery */
|
||||||
if(!page->generation) {
|
#ifdef MZ_USE_PLACES
|
||||||
page->generation = 1;
|
if(!page->generation && !is_a_master_page)
|
||||||
|
#else
|
||||||
/* remove page */
|
if(!page->generation)
|
||||||
if(page->prev) page->prev->next = page->next; else
|
|
||||||
gc->gen0.big_pages = page->next;
|
|
||||||
if(page->next) page->next->prev = page->prev;
|
|
||||||
|
|
||||||
GCVERBOSEPAGE(gc, "MOVING BIG PAGE TO GEN1", page);
|
|
||||||
|
|
||||||
backtrace_new_page(gc, page);
|
|
||||||
|
|
||||||
/* add to gen1 */
|
|
||||||
page->next = gc->gen1_pages[PAGE_BIG];
|
|
||||||
page->prev = NULL;
|
|
||||||
if(page->next) page->next->prev = page;
|
|
||||||
gc->gen1_pages[PAGE_BIG] = page;
|
|
||||||
|
|
||||||
/* if we're doing memory accounting, then we need to make sure the
|
|
||||||
btc_mark is right */
|
|
||||||
#ifdef NEWGC_BTC_ACCOUNT
|
|
||||||
BTC_set_btc_mark(gc, BIG_PAGE_TO_OBJHEAD(page));
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
promote_marked_gen0_big_page(gc, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
page->marked_on = 1;
|
page->marked_on = 1;
|
||||||
|
@ -2764,6 +2787,19 @@ static void propagate_marks(NewGC *gc)
|
||||||
propagate_marks_worker(gc, mark_table, p);
|
propagate_marks_worker(gc, mark_table, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MZ_USE_PLACES
|
||||||
|
static void promote_marked_gen0_big_pages(NewGC *gc) {
|
||||||
|
mpage *page;
|
||||||
|
mpage *next;
|
||||||
|
|
||||||
|
for (page = gc->gen0.big_pages; page ; page = next) {
|
||||||
|
next = page->next;
|
||||||
|
if (page->marked_on) {
|
||||||
|
promote_marked_gen0_big_page(gc, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void *GC_resolve(void *p)
|
void *GC_resolve(void *p)
|
||||||
{
|
{
|
||||||
|
@ -3930,6 +3966,10 @@ static void garbage_collect(NewGC *gc, int force_full, int switching_master)
|
||||||
if (premaster_or_place_gc(gc))
|
if (premaster_or_place_gc(gc))
|
||||||
#endif
|
#endif
|
||||||
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(gc), NULL);
|
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(gc), NULL);
|
||||||
|
#ifdef MZ_USE_PLACES
|
||||||
|
if (postmaster_and_master_gc(gc))
|
||||||
|
promote_marked_gen0_big_pages(gc);
|
||||||
|
#endif
|
||||||
|
|
||||||
TIME_STEP("stacked");
|
TIME_STEP("stacked");
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ void fault_handler(int sn, struct siginfo *si, void *ctx)
|
||||||
if (si->si_code != SEGV_ACCERR) { /*SEGV_MAPERR*/
|
if (si->si_code != SEGV_ACCERR) { /*SEGV_MAPERR*/
|
||||||
if (c == SEGV_MAPERR) {
|
if (c == SEGV_MAPERR) {
|
||||||
printf("SIGSEGV MAPERR si_code %i fault on addr %p\n", c, p);
|
printf("SIGSEGV MAPERR si_code %i fault on addr %p\n", c, p);
|
||||||
|
printf("This often means %p isn't getting marked, and was prematurely freed\n", p);
|
||||||
}
|
}
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
/* I have no idea why this happens on linux */
|
/* I have no idea why this happens on linux */
|
||||||
|
|
|
@ -216,6 +216,10 @@ define psoq
|
||||||
set $scharp = $scharp + 4
|
set $scharp = $scharp + 4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if ( $OT == <<scheme_byte_string_type>>)
|
||||||
|
printf "scheme_byte_string_type "
|
||||||
|
p (char *)((Scheme_Simple_Object *)$O)->u.byte_str_val.string_val
|
||||||
|
end
|
||||||
if ( $OT == <<scheme_unix_path_type>>)
|
if ( $OT == <<scheme_unix_path_type>>)
|
||||||
printf "scheme_unix_path_type "
|
printf "scheme_unix_path_type "
|
||||||
p (char *)((Scheme_Simple_Object *)$O)->u.byte_str_val.string_val
|
p (char *)((Scheme_Simple_Object *)$O)->u.byte_str_val.string_val
|
||||||
|
|
Loading…
Reference in New Issue
Block a user