summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-03-17 21:17:31 +0100
committerNeal H. Walfield <neal@gnu.org>2009-03-17 21:17:31 +0100
commit0b41c0c32736f86bf29c6d9fa7e1c6ad18924386 (patch)
treebdedb2f7d18fae8d5bf15d0e51003360cbe098cd
parent85532309547c936947da9e27e328f0e4f29df323 (diff)
Tweak GC scheduler.
-rw-r--r--benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch11
-rw-r--r--benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch372
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;
}