diff options
author | Neal H. Walfield <neal@gnu.org> | 2009-03-17 21:17:31 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2009-03-17 21:17:31 +0100 |
commit | 0b41c0c32736f86bf29c6d9fa7e1c6ad18924386 (patch) | |
tree | bdedb2f7d18fae8d5bf15d0e51003360cbe098cd | |
parent | 85532309547c936947da9e27e328f0e4f29df323 (diff) |
Tweak GC scheduler.
-rw-r--r-- | benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch | 11 | ||||
-rw-r--r-- | benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch | 372 |
2 files changed, 258 insertions, 125 deletions
diff --git a/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch b/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch index f8a0a1e..00b8c22 100644 --- a/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch +++ b/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch @@ -6,7 +6,7 @@ Tweak the configuration. diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/include/private/gcconfig.h gc.new/include/private/gcconfig.h --- gc/include/private/gcconfig.h 2007-06-29 02:00:09.000000000 +0200 -+++ gc.new/include/private/gcconfig.h 2009-02-23 22:59:56.000000000 +0100 ++++ gc.new/include/private/gcconfig.h 2009-03-05 23:12:04.000000000 +0100 @@ -451,7 +451,28 @@ # define HURD # define I386 @@ -63,3 +63,12 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i # endif # ifdef DARWIN # define OS_TYPE "DARWIN" +@@ -1842,6 +1855,8 @@ + # define CACHE_LINE_SIZE 64 + # ifdef LINUX + # define OS_TYPE "LINUX" ++# define USE_MMAP ++# define USE_MUNMAP + # define LINUX_STACKBOTTOM + # if !defined(GC_LINUX_THREADS) || !defined(REDIRECT_MALLOC) + # define MPROTECT_VDB diff --git a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch index d9cfb56..3ee49bd 100644 --- a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch +++ b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch @@ -6,10 +6,23 @@ Patch to support the Viengoos specific scheduler. To disable it, set GC_viengoos_scheduler to 0. -diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc.orig/allchblk.c gc/allchblk.c ---- gc.orig/allchblk.c 2007-06-07 02:40:07.000000000 +0200 -+++ gc/allchblk.c 2009-02-24 03:07:28.000000000 +0100 -@@ -117,7 +117,9 @@ void GC_print_hblkfreelist() +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/allchblk.c gc.new/allchblk.c +--- gc/allchblk.c 2007-06-07 02:40:07.000000000 +0200 ++++ gc.new/allchblk.c 2009-03-07 21:53:56.000000000 +0100 +@@ -17,6 +17,12 @@ + /* #define DEBUG */ + #include <stdio.h> + #include "private/gc_priv.h" ++#include <stdint.h> ++#include <inttypes.h> ++ ++#ifndef debug ++#define debug(lvl, fmt, ...) do {} while (0) ++#endif + + GC_bool GC_use_entire_heap = 0; + +@@ -117,7 +123,9 @@ void GC_print_hblkfreelist() while (h != 0) { hhdr = HDR(h); sz = hhdr -> hb_sz; @@ -20,7 +33,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i total_free += sz; if (GC_is_black_listed(h, HBLKSIZE) != 0) { GC_printf("start black listed\n"); -@@ -381,31 +383,142 @@ void GC_add_to_fl(struct hblk *h, hdr *h +@@ -381,31 +389,160 @@ void GC_add_to_fl(struct hblk *h, hdr *h #ifdef USE_MUNMAP @@ -33,7 +46,8 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + /* Unmap blocks that haven't been recently touched. This is the only way */ /* way blocks are ever unmapped. */ - void GC_unmap_old(void) +-void GC_unmap_old(void) ++void GC_try_unmap(bool all) { struct hblk * h; hdr * hhdr; @@ -41,28 +55,37 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i unsigned short last_rec, threshold; int i; # define UNMAP_THRESHOLD 6 -- -- for (i = 0; i <= N_HBLK_FLS; ++i) { + -+ uint64_t mapped_start = GC_get_heap_size() - GC_unmapped_bytes; ++ if (all) ++ GC_gcollect (); + ++ void unmap(ptr_t start, size_t bytes) ++ { ++ if (! all) ++ GC_unmap (start, bytes); ++ else ++ munmap (start, bytes); ++ } + +- for (i = 0; i <= N_HBLK_FLS; ++i) { ++ if (! all && GC_viengoos_scheduler && GC_mapped_bytes < MAPPED_THRESHOLD) ++ /* The amount of mapped memory does not exceed the low-water ++ threshold. */ ++ return; ++ ++ uint64_t mapped_at_start = GC_mapped_bytes; + start: -+ if (GC_viengoos_scheduler -+ && (GC_get_heap_size() - GC_unmapped_bytes -+ < 7 * (GC_available_bytes / 8))) { -+ /* The number of mapped bytes is at most 7/8s the available -+ memory. That's good enough for now. (Recall: the high-water -+ mark is 15/16s the available memory.) */ -+ uint64_t mapped_now = GC_get_heap_size() - GC_unmapped_bytes; -+ -+ extern char *program_name; -+ if (0) -+ printf ("%s("VG_THREAD_ID_FMT"): After unmapping %"PRId64" mb, " -+ "%"PRId64"mb used (%"PRId64"mb available)\n", -+ program_name, hurd_myself (), -+ (mapped_start - mapped_now) / 1024 / 1024, -+ mapped_now / 1024 / 1024, -+ (uint64_t) GC_available_bytes / 1024 / 1024); ++ if (! all ++ && GC_viengoos_scheduler ++ && GC_mapped_bytes < 7 * (MAPPED_THRESHOLD / 8)) { ++ /* Unmap at least enough memory such that we are below 7/8s ++ threshold. */ ++ out: ++ debug (1, "After unmapping %"PRId64" mb, " ++ "%"PRId64"mb mapped (threshold: %"PRId64" mb)", ++ (mapped_at_start - GC_mapped_bytes) / 1024 / 1024, ++ GC_mapped_bytes / 1024 / 1024, ++ (uint64_t) MAPPED_THRESHOLD / 1024 / 1024); + return; + } + @@ -80,10 +103,11 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i - hhdr -> hb_flags |= WAS_UNMAPPED; - } + -+ if (GC_viengoos_scheduler ++ if (all ++ || GC_viengoos_scheduler + || ((last_rec > GC_gc_no || last_rec < threshold) + && threshold < GC_gc_no /* not recently wrapped */)) { -+ GC_unmap((ptr_t)h, hhdr -> hb_sz); ++ unmap((ptr_t)h, hhdr -> hb_sz); + hhdr -> hb_flags |= WAS_UNMAPPED; + + if (0) @@ -133,7 +157,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + + /* Unmap if not already unmapped. */ + if (IS_MAPPED (nexthdr)) { -+ GC_unmap((ptr_t)next, nexthdr -> hb_sz); ++ unmap((ptr_t)next, nexthdr -> hb_sz); + nexthdr -> hb_flags |= WAS_UNMAPPED; + } + @@ -170,10 +194,17 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } - } + } ++ ++ goto out; ++} ++ ++void GC_unmap_old(void) ++{ ++ GC_try_unmap (false); } /* Merge all unmapped blocks that are adjacent to other free */ -@@ -413,6 +526,12 @@ void GC_unmap_old(void) +@@ -413,6 +550,12 @@ void GC_unmap_old(void) /* fully mapped or fully unmapped. */ void GC_merge_unmapped(void) { @@ -186,7 +217,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i struct hblk * h, *next; hdr * hhdr, *nexthdr; word size, nextsize; -@@ -600,12 +719,26 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -600,12 +743,26 @@ GC_allochblk_nth(size_t sz, int kind, un size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz); @@ -213,7 +244,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i if (size_avail != size_needed && !GC_use_entire_heap && !GC_dont_gc -@@ -642,7 +775,7 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -642,7 +799,7 @@ GC_allochblk_nth(size_t sz, int kind, un next_size = (signed_word)(thishdr -> hb_sz); if (next_size < size_avail && next_size >= size_needed @@ -222,7 +253,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i continue; } } -@@ -748,10 +881,12 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -748,10 +905,12 @@ GC_allochblk_nth(size_t sz, int kind, un /* hbp may be on the wrong freelist; the parameter n */ /* is important. */ hbp = GC_get_first_part(hbp, hhdr, size_needed, n); @@ -238,22 +269,26 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i /* Add it to map of valid blocks */ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/alloc.c gc.new/alloc.c --- gc/alloc.c 2007-06-22 04:40:30.000000000 +0200 -+++ gc.new/alloc.c 2009-02-24 03:07:16.000000000 +0100 -@@ -15,6 +15,13 @@ ++++ gc.new/alloc.c 2009-03-06 20:42:23.000000000 +0100 +@@ -15,6 +15,17 @@ * */ +#ifdef __gnu_hurd_viengoos__ +#include <viengoos/activity.h> +#include <hurd/as.h> ++#else ++#define debug(lvl, fmt, ...) do {} while (0) +#endif +#include <stdint.h> +#include <sys/time.h> +#include <assert.h> ++#include <inttypes.h> ++#include <stdbool.h> # include "private/gc_priv.h" -@@ -24,6 +31,8 @@ +@@ -24,6 +35,8 @@ # include <sys/types.h> # endif @@ -262,16 +297,14 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i /* * Separate free lists are maintained for different sized objects * up to MAXOBJBYTES. -@@ -223,9 +232,160 @@ void GC_clear_a_few_frames() +@@ -223,9 +236,188 @@ void GC_clear_a_few_frames() /* limits used by blacklisting. */ static word GC_collect_at_heapsize = (word)(-1); +int GC_viengoos_scheduler = 1; -+uintptr_t GC_available_bytes = (uintptr_t) ((256 + 128) * 1024 * 1024); ++uintptr_t GC_available_bytes = (uintptr_t) ((1024 + 717) * 1024 * 1024); +int GC_could_unmap; + -+#define THRESHOLD ((uintptr_t) (15 * (GC_available_bytes / 16))) -+ +#ifdef __gnu_hurd_viengoos__ +static void * +gather_stats (void *arg) @@ -322,29 +355,27 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + panic ("Unknown event and unrequested event: %"PRIdPTR, info.event); + } + -+ extern char *program_name; -+ if (0) -+ printf ("%s("VG_THREAD_ID_FMT"): %s: " -+ "%"PRId64" alloced: %"PRId64"mb, heap: %"PRId64"mb, " -+ "mapped:%"PRId64"mb, unmapped: %"PRId64"mb, " -+ "available: %"PRIdPTR"mb => %"PRIdPTR"mb, " -+ "low-water: %"PRIdPTR"mb\n", -+ program_name, hurd_myself (), -+ info.event == vg_activity_info_stats -+ ? "Period" : DEBUG_BOLD ("PRESSURE"), -+ (uint64_t) (info.event == vg_activity_info_stats -+ ? period : info.pressure.amount), -+ (uint64_t) GC_adj_bytes_allocd() / 1024 / 1024, -+ (uint64_t) GC_get_heap_size () / 1024 / 1024, -+ (uint64_t) (GC_get_heap_size () - GC_unmapped_bytes) -+ / 1024 / 1024, -+ (uint64_t) GC_unmapped_bytes / 1024 / 1024, -+ (uint64_t) old_avail / 1024 / 1024, -+ (uint64_t) GC_available_bytes / 1024 / 1024, -+ (uint64_t) THRESHOLD / 1024 / 1024); ++ debug (1, "%s %"PRId64": " ++ "available: %"PRIdPTR"mb => %"PRIdPTR"mb; " ++ "%"PRId64"mb, heap: %"PRId64"mb - " ++ "mapped: %"PRId64"mb = unmapped: %"PRId64"mb, " ++ "(threshold: %"PRIdPTR"mb); %"PRId64" free", ++ info.event == vg_activity_info_stats ++ ? "Period" : DEBUG_BOLD ("PRESSURE"), ++ (uint64_t) (info.event == vg_activity_info_stats ++ ? period ++ : (((uint64_t) info.pressure.amount ++ * PAGESIZE) / 1024 / 1024)), ++ (uint64_t) old_avail / 1024 / 1024, ++ (uint64_t) GC_available_bytes / 1024 / 1024, ++ (uint64_t) GC_get_heap_size () / 1024 / 1024, ++ (uint64_t) GC_mapped_bytes / 1024 / 1024, ++ (uint64_t) GC_unmapped_bytes / 1024 / 1024, ++ (uint64_t) MAPPED_THRESHOLD / 1024 / 1024, ++ (uint64_t) GC_free_bytes / 1024 / 1024); + if (0 && info.event == vg_activity_info_pressure) -+ printf ("pages to free: %d mb\n", -+ info.pressure.amount * (PAGESIZE / 1024) / 1024); ++ s_printf ("pages to free: %d mb\n", ++ info.pressure.amount * (PAGESIZE / 1024) / 1024); + } +} +#endif @@ -352,16 +383,11 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i /* Have we allocated enough to amortize a collection? */ GC_bool GC_should_collect(void) { -+#ifndef USE_MUNMAP -+# define GC_unmapped_bytes 0 -+#endif -+ + if (GC_viengoos_scheduler) + { -+ int alloced = GC_adj_bytes_allocd(); +#ifdef __gnu_hurd_viengoos__ + static int init; -+ if (! init) ++ if (unlikely (! init)) + { + pthread_t tid; + error_t err = pthread_create (&tid, NULL, gather_stats, NULL); @@ -371,59 +397,96 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + } +#endif + -+ /* Do some clean up if the mapped memory is more than 15/16s the -+ available memory. We choose 15/16s as we need to consider -+ meta-data overhead and as we really want to avoid the system -+ pager kicking in. */ -+ GC_bool r = GC_get_heap_size() - GC_unmapped_bytes > THRESHOLD; ++ /* GC_allochblk_nth calls this function repeatedly without ++ immediately following up with a GC. Once we decide to GC, ++ just return true until it happens. */ ++ static int scheduled_gc_no; ++ if (scheduled_gc_no == GC_gc_no + 1) ++ return true; ++ ++ bool r = false; ++ ++ /* Unmap some memory if the number of mapped bytes exceeds ++ MAPPED_THRESHOLD. */ ++ if (GC_mapped_bytes > MAPPED_THRESHOLD ++ && GC_free_bytes > MAPPED_THRESHOLD / 3) { ++ debug (1, "Unmapping: " ++ "heap: %"PRId64" - unmapped: %"PRId64" = " ++ "mapped: %"PRId64" (threshold: %"PRId64")\n" ++ "free: %"PRId64" (threshold: %"PRId64"); avail: %"PRId64, ++ (uint64_t) GC_get_heap_size() / 1024 / 1024, ++ (uint64_t) GC_unmapped_bytes / 1024 / 1024, ++ (uint64_t) GC_mapped_bytes / 1024 / 1024, ++ (uint64_t) MAPPED_THRESHOLD / 1024 / 1024, ++ (uint64_t) GC_free_bytes / 1024 / 1024, ++ MAPPED_THRESHOLD / 1024 / 1024 / 3, ++ GC_available_bytes / 1024 / 1024); + -+ if (r && (GC_get_heap_size () - GC_unmapped_bytes - alloced -+ > GC_available_bytes / 3)){ + /* The number of unused mapped bytes is greater than a third + of the total available memory. Before doing a GC, try to + unmap some free mapped pages. */ ++ uint64_t mapped = GC_mapped_bytes; + GC_unmap_old (); + -+ r = GC_get_heap_size() - GC_unmapped_bytes > THRESHOLD; ++ debug (1, DEBUG_BOLD ("After unmap: mapped %"PRId64" => %"PRId64" (threshold: %"PRId64"); delta: %"PRId64), ++ (uint64_t) mapped / 1024 / 1024, ++ (uint64_t) GC_mapped_bytes / 1024 / 1024, ++ MAPPED_THRESHOLD / 1024 / 1024, ++ (uint64_t) (mapped - GC_mapped_bytes) / 1024 / 1024); ++ ++ if (GC_mapped_bytes > 7 * (MAPPED_THRESHOLD / 8)) ++ /* Force a GC. We didn't manage to unmap enough. */ ++ r = true; + } + -+ if (r) { -+ if (alloced < GC_available_bytes / 100) -+ /* If we have not allocated anything since the last -+ collection, don't do a collection. */ -+ return FALSE; -+ -+ static int warning; -+ /* Only print this once per-gc. GC_allochblk_nth calls this -+ function repeatedly without immediately following up with -+ a GC. */ -+ if (warning != GC_gc_no) { -+ warning = GC_gc_no; -+ extern char *program_name; -+ if (0) -+ printf ("%s("VG_THREAD_ID_FMT"): Scheduling GC #%u: " -+ "alloced: %"PRId64"mb, heap: %"PRId64"mb, " -+ "mapped: %"PRId64"mb, unmapped: %"PRId64"mb, " -+ "available: %"PRIdPTR"mb, low-water: %"PRIdPTR"mb\n", -+ program_name, hurd_myself (), -+ (uint64_t) GC_gc_no, -+ (uint64_t) alloced / 1024 / 1024, -+ (uint64_t) GC_get_heap_size () / 1024 / 1024, -+ (uint64_t) (GC_get_heap_size () - GC_unmapped_bytes) -+ / 1024 / 1024, -+ (uint64_t) GC_unmapped_bytes / 1024 / 1024, -+ (uint64_t) GC_available_bytes / 1024 / 1024, -+ (uint64_t) THRESHOLD / 1024 / 1024); ++ /* If ++ ++ - the number of mapped bytes is approaching the mapped ++ threshold and the number of unallocated heap bytes is low ++ ++ or ++ ++ - the number of mapped bytes exceeded the mapped threshold ++ and we couldn't unmap enough, ++ ++ then do a GC. */ ++ if ((GC_mapped_bytes > 15 * MAPPED_THRESHOLD / 16 ++ && GC_free_bytes < MAPPED_THRESHOLD / 16) ++ || r) { ++ int alloced = GC_adj_bytes_allocd(); ++ ++ if (alloced < MAPPED_THRESHOLD / 100) ++ /* But not if we've only allocated a few bytes since the ++ last GC. */ ++ { ++ debug (1, "Delaying GC: alloced %d", alloced / 1024 / 1024); ++ return FALSE; + } ++ ++ debug (1, "Scheduling GC #%u: alloced since last gc: %"PRId64"\n" ++ "heap: %"PRId64" mb - unmapped: %"PRId64" mb" ++ " = mapped: %"PRId64" (threshold: %"PRId64"); " ++ "free: %"PRId64" mb, available: %"PRId64" mb", ++ (uint64_t) GC_gc_no, ++ (uint64_t) alloced / 1024 / 1024, ++ (uint64_t) GC_get_heap_size () / 1024 / 1024, ++ (uint64_t) GC_unmapped_bytes / 1024 / 1024, ++ (uint64_t) GC_mapped_bytes / 1024 / 1024, ++ (uint64_t) MAPPED_THRESHOLD / 1024 / 1024, ++ (uint64_t) GC_free_bytes / 1024 / 1024, ++ (uint64_t) GC_available_bytes / 1024 / 1024); ++ ++ scheduled_gc_no = GC_gc_no + 1; ++ return TRUE; + } + -+ return r; ++ return FALSE; + } + else return(GC_adj_bytes_allocd() >= min_bytes_allocd() || GC_heapsize >= GC_collect_at_heapsize); } -@@ -256,6 +416,8 @@ void GC_maybe_gc(void) +@@ -256,6 +448,8 @@ void GC_maybe_gc(void) n_partial_gcs = 0; return; } else { @@ -432,7 +495,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i # ifdef PARALLEL_MARK GC_wait_for_reclaim(); # endif -@@ -266,6 +428,7 @@ void GC_maybe_gc(void) +@@ -266,6 +460,7 @@ void GC_maybe_gc(void) (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd); } @@ -440,7 +503,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i GC_promote_black_lists(); (void)GC_reclaim_all((GC_stop_func)0, TRUE); GC_clear_marks(); -@@ -275,7 +438,11 @@ void GC_maybe_gc(void) +@@ -275,7 +470,11 @@ void GC_maybe_gc(void) } else { n_partial_gcs++; } @@ -452,7 +515,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i /* We try to mark with the world stopped. */ /* If we run out of time, this turns into */ /* incremental marking. */ -@@ -294,6 +461,8 @@ void GC_maybe_gc(void) +@@ -294,6 +493,8 @@ void GC_maybe_gc(void) GC_n_attempts++; } } @@ -461,7 +524,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } } -@@ -325,6 +494,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -325,6 +526,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ "Initiating full world-stop collection %lu after %ld allocd bytes\n", (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd); } @@ -472,7 +535,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i GC_promote_black_lists(); /* Make sure all blocks have been reclaimed, so sweep routines */ /* don't see cleared mark bits. */ -@@ -337,7 +510,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -337,7 +542,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ if ((GC_find_leak || stop_func != GC_never_stop_func) && !GC_reclaim_all(stop_func, FALSE)) { /* Aborted. So far everything is still consistent. */ @@ -482,7 +545,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } GC_invalidate_mark_state(); /* Flush mark stack. */ GC_clear_marks(); -@@ -354,7 +528,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -354,7 +560,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ GC_unpromote_black_lists(); } /* else we claim the world is already still consistent. We'll */ /* finish incrementally. */ @@ -492,7 +555,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } GC_finish_collection(); if (GC_print_stats) { -@@ -362,7 +537,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -362,7 +569,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ GC_log_printf("Complete collection took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); } @@ -504,7 +567,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } -@@ -390,6 +568,8 @@ void GC_collect_a_little_inner(int n) +@@ -390,6 +600,8 @@ void GC_collect_a_little_inner(int n) if (GC_dont_gc) return; if (GC_incremental && GC_collection_in_progress()) { @@ -513,7 +576,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i for (i = GC_deficit; i < GC_RATE*n; i++) { if (GC_mark_some((ptr_t)0)) { /* Need to finish a collection */ -@@ -415,6 +595,8 @@ void GC_collect_a_little_inner(int n) +@@ -415,6 +627,8 @@ void GC_collect_a_little_inner(int n) } if (GC_deficit > 0) GC_deficit -= GC_RATE*n; if (GC_deficit < 0) GC_deficit = 0; @@ -522,7 +585,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i } else { GC_maybe_gc(); } -@@ -904,6 +1086,8 @@ GC_bool GC_expand_hp_inner(word n) +@@ -904,6 +1118,8 @@ GC_bool GC_expand_hp_inner(word n) /* Force GC before we are likely to allocate past expansion_slop */ GC_collect_at_heapsize = GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE; @@ -531,7 +594,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i # if defined(LARGE_CONFIG) if (GC_collect_at_heapsize < GC_heapsize /* wrapped */) GC_collect_at_heapsize = (word)(-1); -@@ -1021,3 +1205,410 @@ ptr_t GC_allocobj(size_t gran, int kind) +@@ -1021,3 +1237,452 @@ ptr_t GC_allocobj(size_t gran, int kind) return(*flh); } @@ -588,6 +651,7 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + +#ifdef RM_INTERN +# include "../viengoos/zalloc.h" ++# include "../viengoos/timer.h" +#else +# include <stdlib.h> +#endif @@ -596,12 +660,33 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i +#include <hurd/ihash.h> +#include <stddef.h> +#include <string.h> ++#include <stdbool.h> + +#ifdef __gnu_hurd_viengoos__ +# include <viengoos/bits/sys.h> +# include <s-printf.h> +# include <hurd/thread.h> +# include <viengoos/misc.h> ++ ++# ifndef NPROFILE ++# include "../viengoos/debug.h" ++ ++static void ++profile_command (int argc, char *argv[]) ++{ ++ profile_stats_dump (); ++} ++ ++static struct debug_command profile_debug = ++ { ++ .name = "profile", ++ .short_name = 0, ++ .help = "Display profile data.", ++ .function = profile_command ++ }; ++ ++# endif ++ +#else +# include <pthread.h> +# include <sys/time.h> @@ -632,7 +717,11 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i +now (void) +{ +#ifdef __gnu_hurd_viengoos__ -+ return VG_TIME->ns_since_boot * 1000; ++# ifdef RM_INTERN ++ return time_data.ns_since_boot / 1000; ++# else ++ return VG_TIME->ns_since_boot / 1000; ++# endif +#else + struct timeval t; + struct timezone tz; @@ -656,16 +745,26 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i +}; + +/* The number of threads we support. */ -+#define THREADS 4 ++#ifdef RM_INTERN ++# define THREADS 1 ++#else ++# define THREADS 4 ++#endif +static int thread_count; + +struct profile_block +{ +#ifdef __gnu_hurd_viengoos__ -+# define MYSELF() hurd_myself () ++# ifdef RM_INTERN ++# define MYSELF() 0 ++# else ++# define MYSELF() hurd_myself () ++# endif ++# define THREAD_FMT VG_THREAD_ID_FMT + vg_thread_id_t tid; +#else +# define MYSELF() pthread_self () ++# define THREAD_FMT "%d" + pthread_t tid; +#endif + @@ -705,6 +804,11 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + + /* New thread. */ + ++#ifdef RM_INTERN ++ if (thread_count == 0) ++ debug_register (&profile_debug); ++#endif ++ + i = __sync_fetch_and_add (&thread_count, 1); + if (i >= THREADS) + panic ("More threads than profile space available!"); @@ -826,7 +930,8 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + order[j + 1] = t; + } + -+ s_printf ("Thread: "VG_THREAD_ID_FMT"\n", pb->tid); ++#define MAX(a, b) ((a) > (b) ? (a) : (b)) ++ s_printf ("Thread: "THREAD_FMT"\n", pb->tid); + for (j = 0; j < count; j ++) + { + i = order[j]; @@ -850,9 +955,10 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + pb->call_sites[i].time / pb->call_sites[i].calls, + (int) ((10 * pb->call_sites[i].time) + / pb->call_sites[i].calls) % 10, -+ (int) ((100 * pb->call_sites[i].time) / (n - pb->epoch)), + (int) ((100 * pb->call_sites[i].time) -+ / pb->profiled_time)); ++ / MAX (n - pb->epoch, 1)), ++ (int) ((100 * pb->call_sites[i].time) ++ / MAX (pb->profiled_time, 1))); + } + + s_printf ("profiled time: %"PRId64" ms (%d%%), calls: %"PRId64"\n", @@ -940,11 +1046,29 @@ diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.i + else + site->nested_calls ++; +} ++#endif +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/include/private/gc_priv.h gc.new/include/private/gc_priv.h +--- gc/include/private/gc_priv.h 2007-06-24 04:01:15.000000000 +0200 ++++ gc.new/include/private/gc_priv.h 2009-03-06 16:53:23.000000000 +0100 +@@ -2037,4 +2037,15 @@ extern void GC_reset_fault_handler(void) + + # endif /* Need to handle address faults. */ + ++#include <stdint.h> ++extern uintptr_t GC_available_bytes; + ++#ifndef USE_MUNMAP ++# define GC_unmapped_bytes 0 +#endif -diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -rup gc.orig/os_dep.c gc/os_dep.c ---- gc.orig/os_dep.c 2007-06-29 21:17:44.000000000 +0200 -+++ gc/os_dep.c 2009-02-21 02:33:55.000000000 +0100 ++ ++#define MAPPED_THRESHOLD (15 * (GC_available_bytes / 16)) ++#define GC_mapped_bytes (GC_heapsize - GC_unmapped_bytes) ++#define GC_free_bytes (GC_large_free_bytes - GC_unmapped_bytes) ++ + # endif /* GC_PRIVATE_H */ +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/os_dep.c gc.new/os_dep.c +--- gc/os_dep.c 2007-06-29 21:17:44.000000000 +0200 ++++ gc.new/os_dep.c 2009-03-01 21:06:48.000000000 +0100 @@ -2064,6 +2064,17 @@ ptr_t GC_unmap_end(ptr_t start, size_t b return end_addr; } |