summaryrefslogtreecommitdiff
path: root/benchmarks
diff options
context:
space:
mode:
authorneal <neal>2008-06-27 15:17:27 +0000
committerneal <neal>2008-06-27 15:17:27 +0000
commitc314b447a633a3aa2d1e4a882675038fd381e873 (patch)
treec3d2625fc63af15c7e6200203a5347e68f192713 /benchmarks
parent8305c7cd3d379fda42cee8c58783bf2ae52f4ff0 (diff)
hurd/
2008-06-27 Neal H. Walfield <neal@gnu.org> * activity.h (RM_activity_stats): Don't define. (RM_activity_info): Replace with this. (struct activity_stats): Add field pressure_local. Make field pressure an 8 bit integer. (struct activity_stats_buffer): Remove structure. (struct activity_info): Replace with this structure. (activity_info_stats): Define. (activity_info_pressure): Likewise. (activity_stats): Remove method. (activity_info): Replace with this. viengoos/ 2008-06-27 Neal H. Walfield <neal@gnu.org> * activity.h (struct activity): Add fields free_bad_karma, free_goal, free_allocations and free_initial_allocation. * rm.h (rm_method_id_string): Replace RM_activity_stats handling with RM_activity_info handling. * thread.h (THREAD_WAIT_STATS): Remove. (THREAD_WAIT_ACTIVITY_INFO): Replace with this. (struct thread): Add field wait_reason_arg2. * ager.c (update_stats): Account for local pressure when calculating availability. Don't use activity_stats to inform threads of new statistics but activity_info. * object.c (object_desc_claim): Adjust the activity's FREE_GOAL, FREE_ALLOCATIONS, and FRAMES_EXCLUDED fields as appropriate. * pager.c (pager_collect): When selecting a victim, don't include an activity's excluded frames in its allocation. Don't even consider activities for which FREE_ALLOCATIONS is non-zero. Having selected a victim, don't increase the pressure do drastically. Update the local pressure. Having selected a victim from which to revoke pages, send any waiting threads a message to free memory. If VICTIM->FREE_BAD_KARMA is 0, assume that the memory will be freed and give the activity 100 claims to do it. If the activity has bad karma, decrease it by one. * server.c (server_loop): Replace activity_stats implementation with implementation appropriate for activity_info. hieronymus/ 2008-06-27 Neal H. Walfield <neal@gnu.org> * hieronymus.c (do_gather_stats): Change to use activity_info instead of activity_stats. (main): Introduce code to delay process creation. ruth/ 2008-06-27 Neal H. Walfield <neal@gnu.org> * ruth.c (main): Update to use activity_info instead of activity_stats. benchmarks/ 2008-06-27 Neal H. Walfield <neal@gnu.org> * shared-memory-distribution.c (main): Update to use activity_info instead of activity_status. * activity-distribution.c (main): Likewise. * GCbench.c: Include <stdint.h> and <stdbool.h>. (now): New function. (struct stats): Add fields time, gcs and iter. (have_a_hog): New variable. (mem_hog) [__gnu_hurd_viengoos__]: Rename from this... (helper) [__gnu_hurd_viengoos__]: ... to this. Use activity_info, not activity_stats. Gather more data. (helper) [! __gnu_hurd_viengoos__]: New function. (tid): Rename from this... (helper_tid): ... to this. (helper_fork) [__gnu_hurd_viengoos__]: Name activities. (main): Improve output. benchmarks/boehm-gc/ 2008-06-27 Neal H. Walfield <neal@gnu.org> * patches/05-viengoos-scheduler.patch: Update to use activity_info in place of activity_stats. Listen for pressure messages and act appropriately. Tighten adaptive code. Improve profiling code.
Diffstat (limited to 'benchmarks')
-rw-r--r--benchmarks/ChangeLog19
-rw-r--r--benchmarks/GCbench.c219
-rw-r--r--benchmarks/activity-distribution.c46
-rw-r--r--benchmarks/boehm-gc/ChangeLog6
-rw-r--r--benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch580
-rw-r--r--benchmarks/shared-memory-distribution.c55
6 files changed, 636 insertions, 289 deletions
diff --git a/benchmarks/ChangeLog b/benchmarks/ChangeLog
index 02bf58b..98f58f4 100644
--- a/benchmarks/ChangeLog
+++ b/benchmarks/ChangeLog
@@ -1,3 +1,22 @@
+2008-06-27 Neal H. Walfield <neal@gnu.org>
+
+ * shared-memory-distribution.c (main): Update to use activity_info
+ instead of activity_status.
+ * activity-distribution.c (main): Likewise.
+
+ * GCbench.c: Include <stdint.h> and <stdbool.h>.
+ (now): New function.
+ (struct stats): Add fields time, gcs and iter.
+ (have_a_hog): New variable.
+ (mem_hog) [__gnu_hurd_viengoos__]: Rename from this...
+ (helper) [__gnu_hurd_viengoos__]: ... to this. Use activity_info,
+ not activity_stats. Gather more data.
+ (helper) [! __gnu_hurd_viengoos__]: New function.
+ (tid): Rename from this...
+ (helper_tid): ... to this.
+ (helper_fork) [__gnu_hurd_viengoos__]: Name activities.
+ (main): Improve output.
+
2008-06-23 Neal H. Walfield <neal@gnu.org>
* GCbench.c (struct stats) [__gnu_hurd_viengoos__]: New structure.
diff --git a/benchmarks/GCbench.c b/benchmarks/GCbench.c
index 44e3cc2..ab05665 100644
--- a/benchmarks/GCbench.c
+++ b/benchmarks/GCbench.c
@@ -52,18 +52,41 @@
# include <gc/gc.h>
#endif
+#include <stdint.h>
+#include <stdbool.h>
+
+static inline uint64_t
+now (void)
+{
+ struct timeval t;
+ struct timezone tz;
+
+ if (gettimeofday( &t, &tz ) == -1)
+ return 0;
+ return (t.tv_sec * 1000000ULL + t.tv_usec);
+}
+uint64_t epoch;
+
#include <assert.h>
-#ifdef __gnu_hurd_viengoos__
-#define STATS 1000
+#define STATS 5000
+
struct stats
{
int alloced[2];
int available[2];
+ uint64_t time;
int period;
-} stats[1000];
+ int gcs;
+ int iter;
+} stats[STATS];
int stat_count;
+static int done;
+
+static int iter;
+
+#ifdef __gnu_hurd_viengoos__
#include <hurd/storage.h>
#include <hurd/cap.h>
#include <hurd/activity.h>
@@ -71,18 +94,17 @@ int stat_count;
#include <hurd/anonymous.h>
#include <string.h>
-static int done;
-
addr_t gc_activity;
addr_t hog_activity;
+bool have_a_hog = false;
void *
-mem_hog (void *arg)
+helper (void *arg)
{
pthread_setactivity_np (hog_activity);
- struct activity_stats_buffer buffer;
+ struct activity_info info;
void wait_read_stats (void)
{
@@ -90,82 +112,94 @@ mem_hog (void *arg)
/* First the main thread. */
error_t err;
- err = rm_activity_stats (gc_activity,
- stat_count == 0 ? 0 : buffer.stats[0].period + 1,
- &buffer, &count);
+
+ err = rm_activity_info (gc_activity, activity_info_stats,
+ stat_count == 0
+ ? 0 : stats[stat_count - 1].period + 1,
+ &info);
assert_perror (err);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
stats[stat_count].alloced[0]
- = buffer.stats[0].clean + buffer.stats[0].dirty
- + buffer.stats[0].pending_eviction;
- stats[stat_count].available[0] = buffer.stats[0].available;
+ = info.stats.stats[0].clean + info.stats.stats[0].dirty
+ + info.stats.stats[0].pending_eviction;
+ stats[stat_count].available[0] = info.stats.stats[0].available;
- stats[stat_count].period = buffer.stats[0].period;
+ stats[stat_count].time = now () - epoch;
+ stats[stat_count].period = info.stats.stats[0].period;
+ stats[stat_count].gcs = GC_gc_no;
+ stats[stat_count].iter = iter;
/* Then, the hog. */
- err = rm_activity_stats (hog_activity,
- stat_count == 0 ? 0 : buffer.stats[0].period,
- &buffer, &count);
+ err = rm_activity_info (hog_activity, activity_info_stats,
+ stat_count == 0
+ ? 0 : stats[stat_count - 1].period + 1,
+ &info);
assert_perror (err);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
stats[stat_count].alloced[1]
- = buffer.stats[0].clean + buffer.stats[0].dirty
- + buffer.stats[0].pending_eviction;
- stats[stat_count].available[1] = buffer.stats[0].available;
+ = info.stats.stats[0].clean + info.stats.stats[0].dirty
+ + info.stats.stats[0].pending_eviction;
+ stats[stat_count].available[1] = info.stats.stats[0].available;
stat_count ++;
if (stat_count % 10 == 0)
debug (0, DEBUG_BOLD ("Period %d"), stat_count);
}
- /* Wait a minute before starting. */
- int i;
- for (i = 0; i < 30; i ++)
- wait_read_stats ();
+ if (have_a_hog)
+ {
+ /* Wait a minute before starting. */
+ int i;
+ for (i = 0; i < 20; i ++)
+ wait_read_stats ();
- /* Now, allocate a 10MB chunk of memory every 2 seconds until we've
- allocate half the initially available memory. */
+ /* Now, allocate a 10MB chunk of memory every 2 seconds until we've
+ allocate half the initially available memory. */
- int available = stats[1].available[0] * PAGESIZE;
+ int available = stats[1].available[0] * PAGESIZE;
- printf (DEBUG_BOLD ("mem hog starting (avail: %d, period: %d)!") "\n",
- available, stats[stat_count - 1].period);
+ printf (DEBUG_BOLD ("mem hog starting (avail: %d)!") "\n", available);
- /* The chunk size. */
- int s = 5 * 1024 * 1024;
- int total = available / 2 / s;
- struct anonymous_pager *pagers[total];
- void *buffers[total];
+ /* The chunk size. */
+ int s = 5 * 1024 * 1024;
+ int total = available / 2 / s;
+ struct anonymous_pager *pagers[total];
+ void *buffers[total];
- int c;
- for (c = 0; c < total && ! done; c ++)
- {
- pagers[c]
- = anonymous_pager_alloc (hog_activity, NULL, s, MAP_ACCESS_ALL,
- OBJECT_POLICY (false, OBJECT_PRIORITY_LRU), 0,
- NULL, &buffers[c]);
- assert (pagers[c]);
- assert (buffers[c]);
+ int c;
+ for (c = 0; c < total && ! done; c ++)
+ {
+ pagers[c]
+ = anonymous_pager_alloc (hog_activity, NULL, s, MAP_ACCESS_ALL,
+ OBJECT_POLICY (false, OBJECT_PRIORITY_LRU), 0,
+ NULL, &buffers[c]);
+ assert (pagers[c]);
+ assert (buffers[c]);
- memset (buffers[c], 0, s);
+ memset (buffers[c], 0, s);
- wait_read_stats ();
- }
+ wait_read_stats ();
+ }
- /* Wait a minute before freeing. */
- for (i = 0; i < 30 && ! done; i ++)
- wait_read_stats ();
+ /* Wait a minute before freeing. */
+ for (i = 0; i < 20 && ! done; i ++)
+ wait_read_stats ();
- printf (DEBUG_BOLD ("mem hog releasing memory!") "\n");
+ printf (DEBUG_BOLD ("mem hog releasing memory!") "\n");
- /* Release the memory. */
- for (i = 0; i < total && ! done; i ++)
- {
- wait_read_stats ();
+ /* Release the memory. */
+ for (i = 0; i < total && ! done; i ++)
+ {
+ wait_read_stats ();
- printf (DEBUG_BOLD ("release: %d!") "\n", i);
- anonymous_pager_destroy (pagers[i]);
+ printf (DEBUG_BOLD ("release: %d!") "\n", i);
+ anonymous_pager_destroy (pagers[i]);
+ }
}
/* Finally, wait until the main thread is done. */
@@ -174,24 +208,55 @@ mem_hog (void *arg)
return 0;
}
+#else
+#define have_a_hog false
+
+void *
+helper (void *arg)
+{
+ while (! done)
+ {
+ sleep (2);
+ stats[stat_count].alloced[0] = GC_get_heap_size ();
+ stats[stat_count].available[0] = 0;
+ stats[stat_count].time = now () - epoch;
+ stats[stat_count].gcs = GC_gc_no;
+ stats[stat_count].iter = iter;
+ stat_count ++;
+ }
+
+ return 0;
+}
+#endif
+
-pthread_t tid;
+pthread_t helper_tid;
void
-mem_hog_fork (void)
+helper_fork (void)
{
+ int err;
+
+#ifdef __gnu_hurd_viengoos__
gc_activity = storage_alloc (ADDR_VOID,
cap_activity_control, STORAGE_LONG_LIVED,
OBJECT_POLICY_DEFAULT, ADDR_VOID).addr;
if (ADDR_IS_VOID (gc_activity))
panic ("Failed to allocate main activity");
+ struct object_name name;
+ snprintf (&name.name[0], sizeof (name.name), "gc.%x", l4_myself ());
+ rm_object_name (ADDR_VOID, gc_activity, name);
+
hog_activity = storage_alloc (ADDR_VOID,
cap_activity_control, STORAGE_LONG_LIVED,
OBJECT_POLICY_DEFAULT, ADDR_VOID).addr;
if (ADDR_IS_VOID (hog_activity))
panic ("Failed to allocate hog activity");
+ snprintf (&name.name[0], sizeof (name.name), "hog.%x", l4_myself ());
+ rm_object_name (ADDR_VOID, hog_activity, name);
+
/* We give the main thread and the hog the same priority and
weight. */
struct activity_policy in, out;
@@ -202,7 +267,6 @@ mem_hog_fork (void)
in.child_rel.priority = 2;
in.child_rel.weight = 20;
- error_t err;
err = rm_activity_policy (ADDR_VOID,
ACTIVITY_POLICY_CHILD_REL_SET, in, &out);
assert (err == 0);
@@ -217,11 +281,10 @@ mem_hog_fork (void)
pthread_setactivity_np (gc_activity);
+#endif
- err = pthread_create (&tid, NULL, mem_hog, NULL);
- assert_perror (err);
+ pthread_create (&helper_tid, NULL, helper, NULL);
}
-#endif
#if 1
#define DEBUG(fmt, ...)
@@ -400,10 +463,11 @@ int main() {
extern int GC_print_stats;
// GC_print_stats = 1;
extern int GC_viengoos_scheduler;
- // GC_viengoos_scheduler = 0;
-#ifdef __gnu_hurd_viengoos__
- mem_hog_fork ();
-#endif
+ GC_viengoos_scheduler = 1;
+
+ helper_fork ();
+ epoch = now ();
+
Node root;
Node longLivedTree;
@@ -465,10 +529,9 @@ int main() {
PrintDiagnostics();
#define ITERATIONS 100
- int j;
- for (j = 0; j < ITERATIONS; j ++)
+ for (iter = 0; iter < ITERATIONS; iter ++)
{
- printf ("Iteration %d\n", j);
+ printf ("Iteration %d\n", iter);
for (d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
TimeConstruction(d);
}
@@ -495,22 +558,28 @@ int main() {
dump_profile();
# endif
-#ifdef __gnu_hurd_viengoos__
done = 1;
void *status;
- pthread_join (tid, &status);
+ pthread_join (helper_tid, &status);
{
+ printf ("%s scheduler, %smemory hog\n"
+ "time\tgc alloc'd\tgc avail\thog alloc'd\thog avail\tgcs\titeration\n",
+ GC_viengoos_scheduler ? "Viengoos" : "Boehm",
+ have_a_hog ? "" : "no ");
+
int i;
- printf ("period, main alloc'd + hog alloc'd, main avail, hog alloc'd, hog avail\n");
for (i = 0; i < stat_count; i ++)
{
- printf ("%d %d %d %d %d\n",
+ printf ("%lld.%lld\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
+ stats[i].time / 1000000,
+ (stats[i].time / 100000) % 10,
stats[i].period,
stats[i].alloced[0], stats[i].available[0],
- stats[i].alloced[1], stats[i].available[1]);
+ stats[i].alloced[1], stats[i].available[1],
+ stats[i].gcs,
+ stats[i].iter);
}
}
-#endif
}
diff --git a/benchmarks/activity-distribution.c b/benchmarks/activity-distribution.c
index e287d28..cffc288 100644
--- a/benchmarks/activity-distribution.c
+++ b/benchmarks/activity-distribution.c
@@ -5,6 +5,7 @@
#include <errno.h>
#include <string.h>
#include <pthread.h>
+#include <assert.h>
#include <hurd/activity.h>
#include <hurd/storage.h>
@@ -43,10 +44,11 @@ main (int argc, char *argv[])
ADDR_VOID).addr;
struct activity_policy in;
+ in.sibling_rel.priority = i == 0 ? 2 : 1;
in.sibling_rel.weight = i + 1;
struct activity_policy out;
err = rm_activity_policy (activities[i],
- ACTIVITY_POLICY_SIBLING_REL_WEIGHT_SET, in,
+ ACTIVITY_POLICY_SIBLING_REL_SET, in,
&out);
assert (err == 0);
}
@@ -58,14 +60,14 @@ main (int argc, char *argv[])
int available;
{
- int count;
- struct activity_stats_buffer buffer;
+ struct activity_info info;
- err = rm_activity_stats (activity, 1, &buffer, &count);
+ err = rm_activity_info (activity, activity_info_stats, 1, &info);
assert (err == 0);
- assert (count > 0);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count >= 1);
- available = buffer.stats[0].available * PAGESIZE;
+ available = info.stats.stats[0].available * PAGESIZE;
}
printf ("%d kb memory available\n", available / 1024);
@@ -153,26 +155,29 @@ main (int argc, char *argv[])
uintptr_t next_period = 0;
for (i = 0; i < ITERATIONS; i ++)
{
- debug (0, DEBUG_BOLD ("starting iteration %d (%x)"), i, l4_myself ());
+ printf ("Iteration: %d\n", i);
- int count;
- struct activity_stats_buffer buffer;
+ struct activity_info info;
- rm_activity_stats (activity, next_period, &buffer, &count);
- assert (count > 0);
+ rm_activity_info (activity, activity_info_stats,
+ next_period, &info);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
if (i != 0)
- assertx (buffer.stats[0].period != stats[i - 1][0].period,
+ assertx (info.stats.stats[0].period != stats[i - 1][0].period,
"%d == %d",
- buffer.stats[0].period, stats[i - 1][0].period);
+ info.stats.stats[0].period, stats[i - 1][0].period);
- stats[i][0] = buffer.stats[0];
+ stats[i][0] = info.stats.stats[0];
int j;
for (j = 0; j < THREADS; j ++)
{
- rm_activity_stats (activities[j], next_period, &buffer, &count);
- assert (count > 0);
- stats[i][1 + j] = buffer.stats[0];
+ rm_activity_info (activity, activity_info_stats,
+ next_period, &info);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
+ stats[i][1 + j] = info.stats.stats[0];
}
next_period = stats[i][0].period + 1;
@@ -194,10 +199,13 @@ main (int argc, char *argv[])
{
int j;
- printf ("%d ", (int) stats[i][0].period);
+ printf ("%d", (int) stats[i][0].period);
for (j = 0; j < 1 + THREADS; j ++)
- printf ("%d ", (int) stats[i][j].clean + (int) stats[i][j].dirty);
+ printf ("\t%d\t%d\t%d\t%d", (int) stats[i][j].clean,
+ (int) stats[i][j].dirty,
+ (int) stats[i][j].pending_eviction,
+ (int) stats[i][j].discarded);
printf ("\n");
}
diff --git a/benchmarks/boehm-gc/ChangeLog b/benchmarks/boehm-gc/ChangeLog
index ba04584..ae9ad6d 100644
--- a/benchmarks/boehm-gc/ChangeLog
+++ b/benchmarks/boehm-gc/ChangeLog
@@ -1,3 +1,9 @@
+2008-06-27 Neal H. Walfield <neal@gnu.org>
+
+ * patches/05-viengoos-scheduler.patch: Update to use activity_info
+ in place of activity_stats. Listen for pressure messages and act
+ appropriately. Tighten adaptive code. Improve profiling code.
+
2008-06-26 Neal H. Walfield <neal@gnu.org>
* Makefile.am (noinst_LIBRARIES): Remove target.
diff --git a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch
index 816103d..824eba9 100644
--- a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch
+++ b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch
@@ -5,9 +5,11 @@ exit $?
Patch to support the Viengoos specific scheduler. To disable it, set
GC_viengoos_scheduler to 0.
-diff -upr gc-7.0/allchblk.c gc/allchblk.c
---- gc-7.0/allchblk.c 2007-06-07 02:40:07.000000000 +0200
-+++ gc/allchblk.c 2008-06-22 13:13:44.000000000 +0200
+
+Only in gc: 05-viengoos-scheduler.patch.applied
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/allchblk.c gc/allchblk.c
+--- gc-old/allchblk.c 2007-06-07 02:40:07.000000000 +0200
++++ gc/allchblk.c 2008-06-27 17:01:49.000000000 +0200
@@ -117,7 +117,9 @@ void GC_print_hblkfreelist()
while (h != 0) {
hhdr = HDR(h);
@@ -19,7 +21,7 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
total_free += sz;
if (GC_is_black_listed(h, HBLKSIZE) != 0) {
GC_printf("start black listed\n");
-@@ -381,31 +383,130 @@ void GC_add_to_fl(struct hblk *h, hdr *h
+@@ -381,31 +383,135 @@ void GC_add_to_fl(struct hblk *h, hdr *h
#ifdef USE_MUNMAP
@@ -46,10 +48,15 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
+ start:
+ if (GC_viengoos_scheduler
+ && (GC_get_heap_size() - GC_unmapped_bytes
-+ < 6 * (GC_available_bytes / 8))) {
-+ /* The number of mapped bytes is at most 6/8s the available
++ < 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 7/8s the available memory.) */
++ mark is 15/16s the available memory.) */
++ if (0)
++ printf ("%x: After unmapping %d used (%d available)\n",
++ l4_myself (),
++ (GC_get_heap_size() - GC_unmapped_bytes) / PAGESIZE,
++ GC_available_bytes / PAGESIZE);
+ return;
+ }
+
@@ -160,7 +167,7 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
}
/* Merge all unmapped blocks that are adjacent to other free */
-@@ -413,6 +514,12 @@ void GC_unmap_old(void)
+@@ -413,6 +519,12 @@ void GC_unmap_old(void)
/* fully mapped or fully unmapped. */
void GC_merge_unmapped(void)
{
@@ -173,7 +180,7 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
struct hblk * h, *next;
hdr * hhdr, *nexthdr;
word size, nextsize;
-@@ -600,12 +707,26 @@ GC_allochblk_nth(size_t sz, int kind, un
+@@ -600,12 +712,26 @@ GC_allochblk_nth(size_t sz, int kind, un
size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);
@@ -200,7 +207,7 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
if (size_avail != size_needed
&& !GC_use_entire_heap
&& !GC_dont_gc
-@@ -642,7 +763,7 @@ GC_allochblk_nth(size_t sz, int kind, un
+@@ -642,7 +768,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
@@ -209,7 +216,7 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
continue;
}
}
-@@ -748,10 +869,12 @@ GC_allochblk_nth(size_t sz, int kind, un
+@@ -748,10 +874,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);
@@ -223,9 +230,10 @@ diff -upr gc-7.0/allchblk.c gc/allchblk.c
if (0 == hbp) return 0;
/* Add it to map of valid blocks */
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.c gc/alloc.c
---- gc-7.0/alloc.c 2008-06-24 18:14:01.000000000 +0200
-+++ gc/alloc.c 2008-06-24 17:35:59.000000000 +0200
+Only in gc: allchblk.c~
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/alloc.c gc/alloc.c
+--- gc-old/alloc.c 2008-06-27 17:02:33.000000000 +0200
++++ gc/alloc.c 2008-06-27 17:01:08.000000000 +0200
@@ -15,6 +15,13 @@
*
*/
@@ -240,24 +248,140 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
# include "private/gc_priv.h"
-@@ -34,8 +41,7 @@ now (void)
+@@ -24,68 +31,7 @@
+ # include <sys/types.h>
+ # endif
- if (gettimeofday( &t, &tz ) == -1)
- return 0;
+-uint64_t gc_time;
+-
+-static inline uint64_t
+-now (void)
+-{
+- struct timeval t;
+- struct timezone tz;
+-
+- if (gettimeofday( &t, &tz ) == -1)
+- return 0;
- return (t.tv_sec * 1000000 + t.tv_usec);
-
-+ return (t.tv_sec * 1000000ULL + t.tv_usec);
- }
+-}
+-
+-static int timing;
+-
+-static uint64_t
+-start_timing (const char *func, int lineno)
+-{
+- static const char *timing_func;
+- static int timing_lineno;
+-
+- if (timing)
+- {
+- printf ("Timing for %s:%d but start_timing called from %s:%d\n",
+- timing_func, timing_lineno, func, lineno);
+- assert (! timing);
+- }
+-
+- timing_func = func;
+- timing_lineno = lineno;
+-
+- timing = 1;
+-
+- return now ();
+-}
+-
+-static void
+-end_timing (const char *func, int lineno, uint64_t start)
+-{
+- uint64_t end = now ();
+-
+- if (! timing)
+- {
+- printf ("Timing not started by end_timing called from %s:%d!\n",
+- func, lineno);
+- assert (! timing);
+- }
+- timing = 0;
+-
+- assert (start <= end);
+- gc_time += end - start;
+-}
+-
+-#define start_timing() \
+- do { \
+- uint64_t start = start_timing (__FUNCTION__, __LINE__)
+-
+-#define end_timing() \
+- end_timing (__FUNCTION__, __LINE__, start); \
+- } while (0)
+-
++#include "profile.h"
- static int timing;
-@@ -286,9 +292,106 @@ void GC_clear_a_few_frames()
+ /*
+ * Separate free lists are maintained for different sized objects
+@@ -286,9 +232,134 @@ void GC_clear_a_few_frames()
/* limits used by blacklisting. */
static word GC_collect_at_heapsize = (word)(-1);
+int GC_viengoos_scheduler = 1;
-+int GC_available_bytes;
++int GC_available_bytes = (256 + 128) * 1024 * 1024;
+int GC_could_unmap;
+
++#define THRESHOLD (15 * (GC_available_bytes / 16))
++
++#ifdef __gnu_hurd_viengoos__
++static void *
++gather_stats (void *arg)
++{
++ pthread_detach (pthread_self ());
++
++ int period = 0;
++ for (;;)
++ {
++ struct activity_info info;
++ error_t err = rm_activity_info (ACTIVITY,
++ activity_info_stats
++ | activity_info_pressure,
++ period, &info);
++ assert_perror (err);
++
++ switch (info.event)
++ {
++ case activity_info_stats:
++ GC_available_bytes = info.stats.stats[0].available_local * PAGESIZE;
++ period = info.stats.stats[0].period + 1;
++ break;
++
++ case activity_info_pressure:
++ if (-info.pressure.amount * PAGESIZE < GC_available_bytes)
++ GC_available_bytes -= -info.pressure.amount * PAGESIZE;
++ else
++ /* Huh? */
++ GC_available_bytes = 0;
++ break;
++
++ default:
++ panic ("Unknown event and unrequested event: %d", info.event);
++ }
++
++ if (0)
++ printf ("%x: %s: %d alloced: %d, heap: %d, "
++ "mapped:%d, unmapped: %d, available: %d, "
++ "low-water: %d\n",
++ l4_myself (),
++ info.event == activity_info_stats
++ ? "Period" : DEBUG_BOLD ("PRESSURE"),
++ (int) (info.event == activity_info_stats
++ ? period : info.pressure.amount),
++ (int) GC_adj_bytes_allocd() / PAGESIZE,
++ (int) GC_get_heap_size () / PAGESIZE,
++ (int) (GC_get_heap_size () - GC_unmapped_bytes) / PAGESIZE,
++ (int) GC_unmapped_bytes / PAGESIZE,
++ (int) GC_available_bytes / PAGESIZE,
++ (int) THRESHOLD / PAGESIZE);
++ }
++}
++#endif
++
/* Have we allocated enough to amortize a collection? */
GC_bool GC_should_collect(void)
{
@@ -273,51 +397,23 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
+ collection, don't do a collection. */
+ return FALSE;
+
-+ static uint64_t last_check;
-+
+#ifdef __gnu_hurd_viengoos__
-+ static struct activity_stats_buffer stats;
-+
-+ struct timeval tp;
-+ gettimeofday (&tp, NULL);
-+ uint64_t t = tp.tv_sec * 1000000ULL + tp.tv_usec;
-+ if (! last_check || t - last_check > 1000000)
-+ /* Last check was more than a second ago. */
++ static int init;
++ if (! init)
+ {
-+ last_check = t;
-+
-+ int count;
-+ error_t err = rm_activity_stats (ACTIVITY, 1, &stats, &count);
++ pthread_t tid;
++ error_t err = pthread_create (&tid, NULL, gather_stats, NULL);
+ assert_perror (err);
+
-+ GC_available_bytes = stats.stats[0].available * PAGESIZE;
-+
-+ if (0)
-+ printf ("Period: %d alloced: %dkb, heap: %dkb, "
-+ "mapped:%dkb, unmapped: %dkb, available: %dkb, "
-+ "low-water: %dkb\n",
-+ (int) stats.stats[0].period,
-+ (int) alloced / 1024,
-+ (int) GC_get_heap_size () / 1024,
-+ (int) (GC_get_heap_size () - GC_unmapped_bytes) / 1024,
-+ (int) GC_unmapped_bytes / 1024,
-+ (int) GC_available_bytes / 1024,
-+ (int) 7 * (GC_available_bytes / 8 / 1024));
++ init = 1;
+ }
-+
-+ int period = stats.stats[0].period;
-+#else
-+#define GC_available_bytes ((256 + 128) * 1024 * 1024)
-+ int period = 0;
+#endif
+
-+ /* Do some clean up if the mapped memory is 7/8s the available
-+ memory. We choose 7/8s as we need to consider meta-data
-+ overhead and as we really want to avoid the system pager
-+ kicking in. */
-+ GC_bool r;
-+ r = ((GC_get_heap_size() - GC_unmapped_bytes)
-+ > 7 * (GC_available_bytes / 8));
++ /* 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;
+
+ if (r && (GC_get_heap_size () - GC_unmapped_bytes - alloced
+ > GC_available_bytes / 3)){
@@ -325,8 +421,8 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
+ of the total available memory. Before doing a GC, try to
+ unmap some free mapped pages. */
+ GC_unmap_old ();
-+ r = ((GC_get_heap_size() - GC_unmapped_bytes)
-+ > 7 * (GC_available_bytes / 8));
++
++ r = GC_get_heap_size() - GC_unmapped_bytes > THRESHOLD;
+ }
+
+ if (r) {
@@ -337,17 +433,17 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
+ if (warning != GC_gc_no) {
+ warning = GC_gc_no;
+ if (0)
-+ printf ("(%d) Scheduling GC: (%d) alloced: %dkb, heap: %dkb, "
++ printf ("Scheduling GC: (%u) alloced: %dkb, heap: %dkb, "
+ "mapped: %dkb, unmapped: %dkb, available: %dkb, "
+ "low-water: %dkb\n",
-+ (int) period, GC_gc_no,
++ GC_gc_no,
+ (int) alloced / 1024,
+ (int) GC_get_heap_size () / 1024,
+ (int) (GC_get_heap_size () - GC_unmapped_bytes)
+ / 1024,
+ (int) GC_unmapped_bytes / 1024,
+ (int) GC_available_bytes / 1024,
-+ (int) 7 * (GC_available_bytes / 8 / 1024));
++ (int) THRESHOLD);
+ }
+ }
+
@@ -357,7 +453,38 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
return(GC_adj_bytes_allocd() >= min_bytes_allocd()
|| GC_heapsize >= GC_collect_at_heapsize);
}
-@@ -396,9 +499,17 @@ GC_bool GC_try_to_collect_inner(GC_stop_
+@@ -319,7 +390,7 @@ void GC_maybe_gc(void)
+ n_partial_gcs = 0;
+ return;
+ } else {
+- start_timing ();
++ profile_start (GC_TIMER);
+
+ # ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+@@ -342,10 +413,10 @@ void GC_maybe_gc(void)
+ n_partial_gcs++;
+ }
+
+- end_timing ();
++ profile_end (GC_TIMER);
+ }
+
+- start_timing ();
++ profile_start (GC_TIMER);
+ /* We try to mark with the world stopped. */
+ /* If we run out of time, this turns into */
+ /* incremental marking. */
+@@ -365,7 +436,7 @@ void GC_maybe_gc(void)
+ }
+ }
+
+- end_timing ();
++ profile_end (GC_TIMER);
+ }
+ }
+
+@@ -396,10 +467,18 @@ GC_bool GC_try_to_collect_inner(GC_stop_
GC_log_printf(
"Initiating full world-stop collection %lu after %ld allocd bytes\n",
(unsigned long)GC_gc_no+1, (long)GC_bytes_allocd);
@@ -372,11 +499,59 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
}
- GC_bool ret = true;
+- start_timing ();
+ GC_bool ret = TRUE;
- start_timing ();
++ profile_start (GC_TIMER);
GC_promote_black_lists();
-@@ -1110,6 +1221,8 @@ ptr_t GC_allocobj(size_t gran, int kind)
+ /* Make sure all blocks have been reclaimed, so sweep routines */
+@@ -414,7 +493,7 @@ GC_bool GC_try_to_collect_inner(GC_stop_
+ && !GC_reclaim_all(stop_func, FALSE)) {
+ /* Aborted. So far everything is still consistent. */
+ ret = FALSE;
+- break;
++ goto out;
+ }
+ GC_invalidate_mark_state(); /* Flush mark stack. */
+ GC_clear_marks();
+@@ -432,7 +511,7 @@ GC_bool GC_try_to_collect_inner(GC_stop_
+ } /* else we claim the world is already still consistent. We'll */
+ /* finish incrementally. */
+ ret = FALSE;
+- break;
++ goto out;
+ }
+ GC_finish_collection();
+ if (GC_print_stats) {
+@@ -441,7 +520,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_
+ MS_TIME_DIFF(current_time,start_time));
+ }
+
+- end_timing ();
++ out:
++ profile_end (GC_TIMER);
+ return ret;
+ }
+
+@@ -470,7 +550,7 @@ void GC_collect_a_little_inner(int n)
+
+ if (GC_dont_gc) return;
+ if (GC_incremental && GC_collection_in_progress()) {
+- start_timing ();
++ profile_start (GC_TIMER);
+
+ for (i = GC_deficit; i < GC_RATE*n; i++) {
+ if (GC_mark_some((ptr_t)0)) {
+@@ -498,7 +578,7 @@ void GC_collect_a_little_inner(int n)
+ if (GC_deficit > 0) GC_deficit -= GC_RATE*n;
+ if (GC_deficit < 0) GC_deficit = 0;
+
+- end_timing ();
++ profile_end (GC_TIMER);
+ } else {
+ GC_maybe_gc();
+ }
+@@ -1110,6 +1190,8 @@ ptr_t GC_allocobj(size_t gran, int kind)
void
GC_dump_stats (void)
{
@@ -385,39 +560,139 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/alloc.
printf ("GC: "
#ifdef THREADS
"multi-threaded"
-@@ -1125,8 +1238,9 @@ GC_dump_stats (void)
+@@ -1125,10 +1207,123 @@ GC_dump_stats (void)
GC_incremental ? "generational" : "stop the world",
GC_dirty_maintained ? "" : "not ");
printf("%d collections\n", (int) GC_gc_no);
- printf ("%lld.%03lld seconds spent collecting\n",
- gc_time / 1000000, (gc_time % 1000000) / 1000);
-+ printf ("%lld.%03lld seconds spent collecting, %lld.%03lld mapping\n",
-+ gc_time / 1000000, (gc_time % 1000000) / 1000,
-+ gc_map_time / 1000000, (gc_map_time % 1000000) / 1000);
printf("Heap size: %d (%d kb)\n",
GC_get_heap_size(), GC_get_heap_size() / 1024);
printf("Total bytes allocated: %d (%d kb)\n",
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/configure gc/configure
---- gc-7.0/configure 2007-06-30 17:40:25.000000000 +0200
-+++ gc/configure 2008-06-23 22:12:43.000000000 +0200
-@@ -21558,14 +21558,6 @@ fi
-
- if test -n "${with_cross_host}"; then
- cat >>confdefs.h <<\_ACEOF
--#define NO_CLOCK 1
--_ACEOF
--
-- cat >>confdefs.h <<\_ACEOF
--#define SMALL_CONFIG 1
--_ACEOF
--
-- cat >>confdefs.h <<\_ACEOF
- #define NO_DEBUGGING 1
- _ACEOF
-
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/include/private/gcconfig.h gc/include/private/gcconfig.h
---- gc-7.0/include/private/gcconfig.h 2008-06-24 18:14:01.000000000 +0200
-+++ gc/include/private/gcconfig.h 2008-06-23 22:12:34.000000000 +0200
+ GC_get_total_bytes (), GC_get_total_bytes () / 1024);
++
++ profile_stats_dump ();
++}
++
++/* profile.c - Profiling support implementation.
++ Copyright (C) 2008 Free Software Foundation, Inc.
++ Written by Neal H. Walfield <neal@gnu.org>.
++
++ This file is part of the GNU Hurd.
++
++ The GNU Hurd is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 3 of the
++ License, or (at your option) any later version.
++
++ The GNU Hurd is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see
++ <http://www.gnu.org/licenses/>. */
++
++#define SIZE 10
++struct site
++{
++ const char *name;
++ uint64_t time;
++ uint64_t start;
++ int calls;
++ int pending;
++} sites[SIZE];
++
++static uint64_t epoch;
++static uint64_t calls;
++static uint64_t total_time;
++/* Number of extant profiling calls. We only update total_time if
++ EXTANT is 0. The result is that the time spent profiling is
++ correct, and the percent of the time profile that a function has
++ been is more meaningful. */
++static int extant;
++
++static inline uint64_t
++now (void)
++{
++ struct timeval t;
++ struct timezone tz;
++
++ if (gettimeofday( &t, &tz ) == -1)
++ return 0;
++ return (t.tv_sec * 1000000ULL + t.tv_usec);
++}
++
++void
++profile_stats_dump (void)
++{
++ uint64_t n = now ();
++
++ int i;
++ for (i = 0; i < SIZE; i ++)
++ if (sites[i].calls)
++ printf ("%s:\t%d calls,\t%lld ms,\t%lld.%d us per call,\t"
++ "%d%% total time,\t%d%% profiled time\n",
++ sites[i].name,
++ sites[i].calls,
++ sites[i].time / 1000,
++ sites[i].time / sites[i].calls,
++ (int) ((10 * sites[i].time) / sites[i].calls) % 10,
++ (int) ((100 * sites[i].time) / (n - epoch)),
++ (int) ((100 * sites[i].time) / total_time));
++
++ printf ("profiled time: %lld ms, calls: %lld\n",
++ total_time / 1000, calls);
++ printf ("uptime: %lld ms\n", (n - epoch) / 1000);
++}
++
++void
++profile_start (uintptr_t id, const char *name)
++{
++ if (! epoch)
++ epoch = now ();
++
++ struct site *site = &sites[id];
++ site->name = name;
++
++ extant ++;
++
++ site->pending ++;
++ if (site->pending == 1)
++ site->start = now ();
+ }
++
++void
++profile_end (uintptr_t id, const char *name)
++{
++ struct site *site = &sites[id];
++ assert (site->pending);
++
++ extant --;
++
++ site->pending --;
++ if (site->pending == 0)
++ {
++ uint64_t n = now ();
++
++ site->time += n - site->start;
++
++ if (extant == 0)
++ total_time += n - site->start;
++
++ site->calls ++;
++ calls ++;
++ }
++}
++
+Only in gc: alloc.c~
+Only in gc: atomic_ops.c
+Only in gc: atomic_ops_sysdeps.S
+Only in gc: autom4te.cache
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/include/private/gcconfig.h gc/include/private/gcconfig.h
+--- gc-old/include/private/gcconfig.h 2008-06-27 17:02:33.000000000 +0200
++++ gc/include/private/gcconfig.h 2008-06-26 10:41:11.000000000 +0200
@@ -1087,6 +1087,8 @@
# ifdef LINUX
# define OS_TYPE "LINUX"
@@ -440,9 +715,16 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/includ
# endif
# ifdef DARWIN
# define OS_TYPE "DARWIN"
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/malloc.c gc/malloc.c
---- gc-7.0/malloc.c 2007-06-06 22:48:35.000000000 +0200
-+++ gc/malloc.c 2008-06-23 22:12:34.000000000 +0200
+Only in gc: libatomic_ops
+Only in gc/libatomic_ops-1.2: .cvsignore
+Only in gc/libatomic_ops-1.2/doc: .cvsignore
+Only in gc/libatomic_ops-1.2/src/atomic_ops: .cvsignore
+Only in gc/libatomic_ops-1.2/src/atomic_ops/sysdeps: .cvsignore
+Only in gc/libatomic_ops-1.2/src: .cvsignore
+Only in gc/libatomic_ops-1.2/tests: .cvsignore
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/malloc.c gc/malloc.c
+--- gc-old/malloc.c 2007-06-06 22:48:35.000000000 +0200
++++ gc/malloc.c 2008-06-26 10:41:13.000000000 +0200
@@ -269,7 +269,9 @@ void * GC_generic_malloc(size_t lb, int
LOCK();
if( EXPECT((op = *opp) == 0, 0) ) {
@@ -468,10 +750,10 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/malloc
}
}
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep.c gc/os_dep.c
---- gc-7.0/os_dep.c 2007-06-29 21:17:44.000000000 +0200
-+++ gc/os_dep.c 2008-06-24 17:35:30.000000000 +0200
-@@ -2064,6 +2064,75 @@ ptr_t GC_unmap_end(ptr_t start, size_t b
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/os_dep.c gc/os_dep.c
+--- gc-old/os_dep.c 2007-06-29 21:17:44.000000000 +0200
++++ gc/os_dep.c 2008-06-26 10:41:13.000000000 +0200
+@@ -2064,6 +2064,18 @@ ptr_t GC_unmap_end(ptr_t start, size_t b
return end_addr;
}
@@ -485,73 +767,16 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
+
+#endif
+
-+uint64_t gc_map_time;
-+
-+static inline uint64_t
-+now (void)
-+{
-+ struct timeval t;
-+ struct timezone tz;
-+
-+ if (gettimeofday( &t, &tz ) == -1)
-+ return 0;
-+ return (t.tv_sec * 1000000ULL + t.tv_usec);
-+
-+}
-+
-+static int timing;
-+
-+static uint64_t
-+start_timing (const char *func, int lineno)
-+{
-+ static const char *timing_func;
-+ static int timing_lineno;
-+
-+ if (timing)
-+ panic ("Timing for %s:%d but start_timing called from %s:%d\n",
-+ timing_func, timing_lineno, func, lineno);
-+
-+ timing_func = func;
-+ timing_lineno = lineno;
-+
-+ timing = 1;
-+
-+ return now ();
-+}
-+
-+static void
-+end_timing (const char *func, int lineno, uint64_t start)
-+{
-+ uint64_t end = now ();
-+
-+ if (! timing)
-+ panic ("Timing not started by end_timing called from %s:%d!\n",
-+ func, lineno);
-+
-+ timing = 0;
-+
-+ if (start > end)
-+ panic ("%lld > %lld!", start, end);
-+ gc_map_time += end - start;
-+}
-+
-+#define start_timing() \
-+ do { \
-+ uint64_t __start = start_timing (__FUNCTION__, __LINE__)
-+
-+#define end_timing() \
-+ end_timing (__FUNCTION__, __LINE__, __start); \
-+ } while (0)
-+
++#include "profile.h"
+
/* Under Win32/WinCE we commit (map) and decommit (unmap) */
/* memory using VirtualAlloc and VirtualFree. These functions */
/* work on individual allocations of virtual memory, made */
-@@ -2077,10 +2146,12 @@ ptr_t GC_unmap_end(ptr_t start, size_t b
+@@ -2077,10 +2089,12 @@ ptr_t GC_unmap_end(ptr_t start, size_t b
/* round the endpoints in both places. */
void GC_unmap(ptr_t start, size_t bytes)
{
-+ start_timing ();
++ profile_start (MAP_TIMER);
+
ptr_t start_addr = GC_unmap_start(start, bytes);
ptr_t end_addr = GC_unmap_end(start, bytes);
@@ -561,7 +786,7 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
# if defined(MSWIN32) || defined(MSWINCE)
while (len != 0) {
MEMORY_BASIC_INFORMATION mem_info;
-@@ -2095,6 +2166,9 @@ void GC_unmap(ptr_t start, size_t bytes)
+@@ -2095,6 +2109,9 @@ void GC_unmap(ptr_t start, size_t bytes)
start_addr += free_len;
len -= free_len;
}
@@ -571,19 +796,19 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
# else
/* We immediately remap it to prevent an intervening mmap from */
/* accidentally grabbing the same address space. */
-@@ -2107,19 +2181,25 @@ void GC_unmap(ptr_t start, size_t bytes)
+@@ -2107,19 +2124,25 @@ void GC_unmap(ptr_t start, size_t bytes)
}
GC_unmapped_bytes += len;
# endif
+
+ out:
-+ end_timing ();
++ profile_end (MAP_TIMER);
}
void GC_remap(ptr_t start, size_t bytes)
{
-+ start_timing ();
++ profile_start (MAP_TIMER);
+
ptr_t start_addr = GC_unmap_start(start, bytes);
ptr_t end_addr = GC_unmap_end(start, bytes);
@@ -598,7 +823,7 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
while (len != 0) {
MEMORY_BASIC_INFORMATION mem_info;
GC_word alloc_len;
-@@ -2137,11 +2217,14 @@ void GC_remap(ptr_t start, size_t bytes)
+@@ -2137,11 +2160,14 @@ void GC_remap(ptr_t start, size_t bytes)
start_addr += alloc_len;
len -= alloc_len;
}
@@ -614,26 +839,26 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
result = mprotect(start_addr, len,
PROT_READ | PROT_WRITE | OPT_PROT_EXEC);
if (result != 0) {
-@@ -2152,6 +2235,9 @@ void GC_remap(ptr_t start, size_t bytes)
+@@ -2152,6 +2178,9 @@ void GC_remap(ptr_t start, size_t bytes)
}
GC_unmapped_bytes -= len;
# endif
+
+ out:
-+ end_timing ();
++ profile_end (MAP_TIMER);
}
/* Two adjacent blocks have already been unmapped and are about to */
-@@ -2160,6 +2246,8 @@ void GC_remap(ptr_t start, size_t bytes)
+@@ -2160,6 +2189,8 @@ void GC_remap(ptr_t start, size_t bytes)
/* unmapped due to alignment constraints. */
void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)
{
-+ start_timing ();
++ profile_start (MAP_TIMER);
+
ptr_t start1_addr = GC_unmap_start(start1, bytes1);
ptr_t end1_addr = GC_unmap_end(start1, bytes1);
ptr_t start2_addr = GC_unmap_start(start2, bytes2);
-@@ -2170,7 +2258,7 @@ void GC_unmap_gap(ptr_t start1, size_t b
+@@ -2170,7 +2201,7 @@ void GC_unmap_gap(ptr_t start1, size_t b
GC_ASSERT(start1 + bytes1 == start2);
if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
@@ -642,19 +867,22 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/os_dep
len = end_addr - start_addr;
# if defined(MSWIN32) || defined(MSWINCE)
while (len != 0) {
-@@ -2190,6 +2278,9 @@ void GC_unmap_gap(ptr_t start1, size_t b
+@@ -2190,6 +2221,9 @@ void GC_unmap_gap(ptr_t start1, size_t b
if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
GC_unmapped_bytes += len;
# endif
+
+ out:
-+ end_timing ();
++ profile_end (MAP_TIMER);
}
#endif /* USE_MUNMAP */
-diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/tests/test.c gc/tests/test.c
---- gc-7.0/tests/test.c 2007-06-19 00:18:01.000000000 +0200
-+++ gc/tests/test.c 2008-06-23 22:12:34.000000000 +0200
+Only in gc: os_dep.c~
+Only in gc: patch.stamp
+Only in gc: profile.h
+diff -upr -x Makefile.in -x configure -x config.guess -x config.sub -x aclocal.m4 gc-old/tests/test.c gc/tests/test.c
+--- gc-old/tests/test.c 2007-06-19 00:18:01.000000000 +0200
++++ gc/tests/test.c 2008-06-26 10:41:14.000000000 +0200
@@ -1334,6 +1334,18 @@ void SetMinimumStack(long minSize)
# endif
# endif
@@ -674,4 +902,4 @@ diff -upr -x config.guess -x config.sub -x Makefile -x Makefile.in gc-7.0/tests/
run_one_test();
check_heap_stats();
# ifndef MSWINCE
-
+Only in gc: unpack.stamp
diff --git a/benchmarks/shared-memory-distribution.c b/benchmarks/shared-memory-distribution.c
index 4043718..04b37c2 100644
--- a/benchmarks/shared-memory-distribution.c
+++ b/benchmarks/shared-memory-distribution.c
@@ -62,14 +62,24 @@ main (int argc, char *argv[])
int count = 0;
while (! terminate)
{
- uintptr_t *p = buffer + (rand () % PAGES) * PAGESIZE;
- t = *p;
-
- count ++;
- if (count % 100000 == 0)
- debug (0, DEBUG_BOLD ("Read %d pages so far"), count);
-
+ int i;
+ for (i = 0; i < 1; i ++)
+ {
+ uintptr_t *p = buffer + (rand () % PAGES) * PAGESIZE;
+ t += *p;
+
+ count ++;
+
+ if (count % 100000 == 0)
+ debug (0, DEBUG_BOLD ("Read %d pages so far"), count);
+ }
+
+#if 0
+ /* ~128Hz. */
+ l4_sleep (l4_time_period (1 << 13));
+#elif 1
l4_thread_switch (tids[rand () % THREADS]);
+#endif
}
printf ("Thread %d: %d operations\n", w, count);
@@ -98,24 +108,26 @@ main (int argc, char *argv[])
{
debug (0, DEBUG_BOLD ("starting iteration %d (%x)"), i, l4_myself ());
- int count;
- struct activity_stats_buffer buffer;
+ struct activity_info info;
- rm_activity_stats (activity, next_period, &buffer, &count);
- assert (count > 0);
+ rm_activity_info (activity, activity_info_stats, next_period, &info);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
if (i != 0)
- assertx (buffer.stats[0].period != stats[i - 1][0].period,
+ assertx (info.stats.stats[0].period != stats[i - 1][0].period,
"%x != %x",
- buffer.stats[0].period, stats[i - 1][0].period);
+ info.stats.stats[0].period, stats[i - 1][0].period);
- stats[i][0] = buffer.stats[0];
+ stats[i][0] = info.stats.stats[0];
int j;
for (j = 0; j < THREADS; j ++)
{
- rm_activity_stats (activities[j], next_period, &buffer, &count);
- assert (count > 0);
- stats[i][1 + j] = buffer.stats[0];
+ rm_activity_info (activity, activity_info_stats, next_period,
+ &info);
+ assert (info.event == activity_info_stats);
+ assert (info.stats.count > 0);
+ stats[i][1 + j] = info.stats.stats[0];
}
next_period = stats[i][0].period + 1;
@@ -137,10 +149,15 @@ main (int argc, char *argv[])
{
int j;
- printf ("%d ", (int) stats[i][0].period);
+ printf ("%d", (int) stats[i][0].period);
for (j = 0; j < 1 + THREADS; j ++)
- printf ("%d ", (int) stats[i][j].clean + (int) stats[i][j].dirty);
+ printf ("\t%d\t%d\t%d\t%d\t%d\t%d", (int) stats[i][j].clean,
+ (int) stats[i][j].dirty,
+ (int) stats[i][j].pending_eviction,
+ (int) stats[i][j].discarded,
+ (int) stats[i][j].freeloading,
+ (int) stats[i][j].freeloaded);
printf ("\n");
}