From: Taylor R Campbell Date: Tue, 5 Apr 2011 00:33:40 +0000 (+0000) Subject: Advise operating system about memory access during GC. X-Git-Tag: 20110426-Gtk~2^2~19 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=f94655bec89fbc42b8c76d20275fc576f26a6925;p=mit-scheme.git Advise operating system about memory access during GC. - Expect sequential access to oldspace during gc_scan_oldspace. - Free heap pages (newspace) before copying tospace over them. - Free tospace pages after saving tospace. The OS hooks are implemented only for Unix, in terms of posix_madvise and madvise. Implementing them for Windows and/or OS/2 is left as an exercise for the reader. --- diff --git a/src/microcode/configure.ac b/src/microcode/configure.ac index b670c64ed..3a8501280 100644 --- a/src/microcode/configure.ac +++ b/src/microcode/configure.ac @@ -717,9 +717,9 @@ AC_CHECK_FUNCS([getcwd gethostbyname gethostname getlogin getpagesize getpgrp]) AC_CHECK_FUNCS([getpt gettimeofday getwd grantpt]) AC_CHECK_FUNCS([kill]) AC_CHECK_FUNCS([lockf]) -AC_CHECK_FUNCS([memcpy mkdir mktime modf]) +AC_CHECK_FUNCS([madvise memcpy mkdir mktime modf]) AC_CHECK_FUNCS([nice ntp_adjtime ntp_gettime]) -AC_CHECK_FUNCS([poll prealloc]) +AC_CHECK_FUNCS([poll posix_madvise prealloc]) AC_CHECK_FUNCS([rename rmdir]) AC_CHECK_FUNCS([select setitimer setpgrp setpgrp2 shmat sigaction]) AC_CHECK_FUNCS([sighold socket statfs strchr strerror strstr strtol]) diff --git a/src/microcode/gcloop.c b/src/microcode/gcloop.c index 52c02189a..8c0a22fc6 100644 --- a/src/microcode/gcloop.c +++ b/src/microcode/gcloop.c @@ -65,6 +65,9 @@ USA. /* For ephemeron layout. */ #include "sdata.h" +/* For memory advice. */ +#include "ostop.h" + static SCHEME_OBJECT ** p_fromspace_start; static SCHEME_OBJECT ** p_fromspace_end; static gc_tospace_allocator_t * gc_tospace_allocator; @@ -226,6 +229,7 @@ save_tospace (gc_walk_proc_t * proc, void * ctx) GUARANTEE_TOSPACE_OPEN (); CHECK_NEWSPACE_SYNC (); ok = (proc (tospace_start, tospace_next, ctx)); + OS_free_pages (tospace_start, tospace_end); CLOSE_TOSPACE (); return (ok); } @@ -235,6 +239,7 @@ discard_tospace (void) { GUARANTEE_TOSPACE_OPEN (); CHECK_NEWSPACE_SYNC (); + OS_free_pages (tospace_start, tospace_end); CLOSE_TOSPACE (); } @@ -387,7 +392,9 @@ std_gc_table (void) void gc_scan_oldspace (SCHEME_OBJECT * scan, SCHEME_OBJECT * end) { + OS_expect_sequential_access (scan, end); run_gc_loop (scan, (&end)); + OS_expect_normal_access (scan, end); } void diff --git a/src/microcode/memmag.c b/src/microcode/memmag.c index 498514e49..d8552fd57 100644 --- a/src/microcode/memmag.c +++ b/src/microcode/memmag.c @@ -30,6 +30,7 @@ USA. #include "history.h" #include "gccode.h" #include "osscheme.h" +#include "ostop.h" #ifdef __WIN32__ extern void win32_allocate_registers (void); @@ -315,6 +316,7 @@ void std_gc_pt2 (void) { SCHEME_OBJECT * p = (get_newspace_ptr ()); + OS_free_pages (heap_start, heap_end); (void) save_tospace (save_tospace_copy, 0); Free = p; diff --git a/src/microcode/nttop.c b/src/microcode/nttop.c index bc89e439a..c68ea13c4 100644 --- a/src/microcode/nttop.c +++ b/src/microcode/nttop.c @@ -1980,3 +1980,24 @@ win32_error_code_to_syserr (DWORD code) default: return (syserr_unknown); } } + +void +OS_expect_sequential_access (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} + +void +OS_expect_normal_access (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} + +void +OS_free_pages (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} diff --git a/src/microcode/os2top.c b/src/microcode/os2top.c index b198fc658..53e11a924 100644 --- a/src/microcode/os2top.c +++ b/src/microcode/os2top.c @@ -2525,3 +2525,24 @@ OS_syscall_names (unsigned long * length, const char *** names) (*length) = ((sizeof (syscall_names_table)) / (sizeof (char *))); (*names) = syscall_names_table; } + +void +OS_expect_sequential_access (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} + +void +OS_expect_normal_access (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} + +void +OS_free_pages (void *start, void *end) +{ + (void) start; /* ignore */ + (void) end; /* ignore */ +} diff --git a/src/microcode/ostop.h b/src/microcode/ostop.h index 06f0273fd..417f7e889 100644 --- a/src/microcode/ostop.h +++ b/src/microcode/ostop.h @@ -38,5 +38,8 @@ extern void OS_save_internal_state (void); extern void OS_restore_internal_state (void); extern void OS_restore_external_state (void); extern const char * OS_error_code_to_message (unsigned int code); +extern void OS_expect_sequential_access (void *start, void *end); +extern void OS_expect_normal_access (void *start, void *end); +extern void OS_free_pages (void *start, void *end); #endif /* SCM_OSTOP_H */ diff --git a/src/microcode/uxtop.c b/src/microcode/uxtop.c index 81b4df9ca..7cb446c00 100644 --- a/src/microcode/uxtop.c +++ b/src/microcode/uxtop.c @@ -558,3 +558,88 @@ OS_syserr_names (unsigned long * length, const char *** names) (*length) = ((sizeof (syserr_names_table)) / (sizeof (char *))); (*names) = syserr_names_table; } + +static unsigned long +round_up (unsigned long n, unsigned long factor) +{ + return (((n + (factor - 1)) / factor) * factor); +} + +static unsigned long +round_down (unsigned long n, unsigned long factor) +{ + return ((n / factor) * factor); +} + +static void +estimate_pages (void *start, void *end, + unsigned long (*round_start) (unsigned long, unsigned long), + unsigned long (*round_end) (unsigned long, unsigned long), + void **addr, size_t *len) +{ + if (end <= start) + { + (*addr) = start; + (*len) = 0; + return; + } + + { + unsigned long page_size = (UX_getpagesize ()); + char *page_start + = ((char *) ((*round_start) (((unsigned long) start), page_size))); + char *page_end + = ((char *) ((*round_end) (((unsigned long) end), page_size))); + (*addr) = ((void *) page_start); + (*len) = ((page_start < page_end) ? (page_end - page_start) : 0); + } +} + +static void +underestimate_pages (void *start, void *end, void **addr, size_t *len) +{ + estimate_pages (start, end, (&round_up), (&round_down), addr, len); +} + +static void +overestimate_pages (void *start, void *end, void **addr, size_t *len) +{ + estimate_pages (start, end, (&round_down), (&round_up), addr, len); +} + +void +OS_expect_sequential_access (void *start, void *end) +{ + void *addr; + size_t len; + overestimate_pages (start, end, (&addr), (&len)); +#if ((defined (HAVE_POSIX_MADVISE)) && (defined (POSIX_MADV_SEQUENTIAL))) + (void) posix_madvise (addr, len, POSIX_MADV_SEQUENTIAL); +#elif ((defined (HAVE_MADVISE)) && (defined (MADV_SEQUENTIAL))) + (void) madvise (addr, len, MADV_SEQUENTIAL); +#endif +} + +void +OS_expect_normal_access (void *start, void *end) +{ + void *addr; + size_t len; + overestimate_pages (start, end, (&addr), (&len)); +#if ((defined (HAVE_POSIX_MADVISE)) && (defined (POSIX_MADV_NORMAL))) + (void) posix_madvise (addr, len, POSIX_MADV_NORMAL); +#elif ((defined (HAVE_MADVISE)) && (defined (MADV_NORMAL))) + (void) madvise (addr, len, MADV_NORMAL); +#endif +} + +void +OS_free_pages (void *start, void *end) +{ + void *addr; + size_t len; + underestimate_pages (start, end, (&addr), (&len)); +#if ((defined (HAVE_MADVISE)) && (defined (MADV_FREE))) + (void) madvise (addr, len, MADV_FREE); +#endif +}