summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Makefile.am1
-rw-r--r--benchmarks/ChangeLog6
-rw-r--r--benchmarks/Makefile.am39
-rw-r--r--benchmarks/activity-distribution.c203
-rw-r--r--benchmarks/boehm-gc/ChangeLog6
-rw-r--r--benchmarks/boehm-gc/Makefile.am117
-rw-r--r--benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch17
-rw-r--r--benchmarks/boehm-gc/patches/02-gc-mach_dep-c.patch18
-rw-r--r--benchmarks/shared-memory-distribution.c148
-rw-r--r--configure.ac2
11 files changed, 564 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index aabaf64..a17c02b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-05-30 Neal H. Walfield <neal@gnu.org>
+
+ * benchmarks: New directory.
+ * configure.ac: Generate benchmarks/Makefile and
+ benchmarks/boehm-gc/Makefile.
+ * Makefile.am (SUBDIRS): Add benchmarks.
+
2008-05-30 Thomas Schwinge <tschwinge@gnu.org>
* configure.ac (missing_progs): Rename to...
diff --git a/Makefile.am b/Makefile.am
index 611d5cf..c8de915 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ SUBDIRS = libl4 platform \
laden viengoos \
. \
ruth \
+ benchmarks \
hieronymus \
$(DOC)
endif
diff --git a/benchmarks/ChangeLog b/benchmarks/ChangeLog
new file mode 100644
index 0000000..314e4fb
--- /dev/null
+++ b/benchmarks/ChangeLog
@@ -0,0 +1,6 @@
+2008-05-30 Neal H. Walfield <neal@gnu.org>
+
+ * Makefile.am: New file.
+ * activity-distribution.c: Likewise.
+ * shared-memory-distribution.c: Likewise.
+ * boehm-gc: New directory.
diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am
new file mode 100644
index 0000000..ac5dc11
--- /dev/null
+++ b/benchmarks/Makefile.am
@@ -0,0 +1,39 @@
+# Makefile.am - Makefile template for hurd-l4.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+bootdir = $(prefix)/boot
+
+if ! ENABLE_TESTS
+SUBDIRS = boehm-gc
+
+boot_PROGRAMS = shared-memory-distribution activity-distribution
+endif
+
+shared_memory_distribution_CPPFLAGS = $(USER_CPPFLAGS)
+shared_memory_distribution_CFLAGS = $(USER_CFLAGS)
+shared_memory_distribution_LDFLAGS = $(USER_LDFLAGS)
+shared_memory_distribution_LDADD = $(USER_LDADD)
+shared_memory_distribution_SOURCES = shared-memory-distribution.c
+
+activity_distribution_CPPFLAGS = $(USER_CPPFLAGS)
+activity_distribution_CFLAGS = $(USER_CFLAGS)
+activity_distribution_LDFLAGS = $(USER_LDFLAGS)
+activity_distribution_LDADD = $(USER_LDADD)
+activity_distribution_SOURCES = activity-distribution.c
+
diff --git a/benchmarks/activity-distribution.c b/benchmarks/activity-distribution.c
new file mode 100644
index 0000000..6ae89d4
--- /dev/null
+++ b/benchmarks/activity-distribution.c
@@ -0,0 +1,203 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <hurd/activity.h>
+#include <hurd/storage.h>
+#include <hurd/startup.h>
+#include <hurd/anonymous.h>
+
+static addr_t activity;
+
+/* Initialized by the machine-specific startup-code. */
+extern struct hurd_startup_data *__hurd_startup_data;
+
+#include <hurd/trace.h>
+
+int
+main (int argc, char *argv[])
+{
+ error_t err;
+
+ extern int output_debug;
+ output_debug = 1;
+
+ activity = __hurd_startup_data->activity;
+
+ printf ("%s running...\n", argv[0]);
+
+#define THREADS 4
+
+ /* The activities. */
+ addr_t activities[THREADS];
+
+ /* Create THREADS activities, each with an increasing weight. */
+ int i;
+ for (i = 0; i < THREADS; i ++)
+ {
+ activities[i] = storage_alloc (activity, cap_activity,
+ STORAGE_LONG_LIVED,
+ OBJECT_POLICY_DEFAULT,
+ ADDR_VOID).addr;
+
+ struct activity_policy in;
+ in.sibling_rel.weight = i + 1;
+ struct activity_policy out;
+ err = rm_activity_policy (activities[i],
+ ACTIVITY_POLICY_SIBLING_REL_WEIGHT_SET, in,
+ &out);
+ assert (err == 0);
+ }
+
+ bool terminate = false;
+ l4_thread_id_t tids[THREADS];
+ for (i = 0; i < THREADS; i ++)
+ tids[i] = l4_nilthread;
+
+ int available;
+ {
+ int count;
+ struct activity_stats_buffer buffer;
+
+ err = rm_activity_stats (activity, 1, &buffer, &count);
+ assert (err == 0);
+ assert (count > 0);
+
+ available = buffer.stats[0].available * PAGESIZE;
+ }
+ printf ("%d kb memory available\n", available / 1024);
+
+ bool my_fill (struct anonymous_pager *anon,
+ void *base, uintptr_t offset,
+ uintptr_t pages,
+ struct exception_info info)
+ {
+ * (int *) (base + offset) = 1;
+ return true;
+ }
+
+ void *worker (void *arg)
+ {
+ int w = (intptr_t) arg;
+
+ tids[w] = l4_myself ();
+
+ pthread_setactivity_np (activities[w]);
+
+ /* Object size. */
+#define SIZE (256 * PAGESIZE)
+
+ /* The number of objects: set so that they fill half of the
+ available memory. */
+#define ITEMS (available / SIZE / 2)
+
+ struct anonymous_pager *pagers[ITEMS];
+ memset (pagers, 0, sizeof (pagers));
+ void *buffers[ITEMS];
+ memset (buffers, 0, sizeof (buffers));
+
+ int t = 0;
+ while (! terminate)
+ {
+ int i = rand () % ITEMS;
+
+ if (! pagers[i])
+ /* Allocate a (discardable) buffer. */
+ {
+ pagers[i]
+ = anonymous_pager_alloc (ADDR_VOID, NULL, SIZE,
+ OBJECT_POLICY (true,
+ OBJECT_PRIORITY_LRU),
+ 0, my_fill, &buffers[i]);
+ assert (pagers[i]);
+ assert (buffers[i]);
+ }
+
+ int j;
+ for (j = 0; j < SIZE / PAGESIZE; j ++)
+ t += * (int *) (buffers[i] + j * PAGESIZE);
+
+ /* 100ms. */
+ l4_sleep (l4_time_period (100 * 1000));
+ }
+
+ /* We need to return t, otherwise, the above loop will be
+ optimized away. */
+ return (void *) t;
+ }
+
+ /* Start the threads. */
+ pthread_t threads[THREADS];
+
+ for (i = 0; i < THREADS; i ++)
+ {
+ err = pthread_create (&threads[i], NULL, worker, (void *) (intptr_t) i);
+ if (err)
+ printf ("Failed to create thread: %s\n", strerror (errno));
+ }
+
+#define ITERATIONS 200
+ struct activity_stats stats[ITERATIONS][1 + THREADS];
+
+ uintptr_t next_period = 0;
+ for (i = 0; i < ITERATIONS; i ++)
+ {
+ debug (0, DEBUG_BOLD ("starting iteration %d (%x)"), i, l4_myself ());
+
+ extern struct trace_buffer rwlock_trace;
+ trace_buffer_dump (&rwlock_trace, 20);
+
+ int count;
+ struct activity_stats_buffer buffer;
+
+ rm_activity_stats (activity, next_period, &buffer, &count);
+ assert (count > 0);
+ if (i != 0)
+ assertx (buffer.stats[0].period != stats[i - 1][0].period,
+ "%d == %d",
+ buffer.stats[0].period, stats[i - 1][0].period);
+
+ stats[i][0] = buffer.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];
+ }
+
+ next_period = stats[i][0].period + 1;
+ }
+
+ terminate = true;
+ for (i = 0; i < THREADS; i ++)
+ {
+ void *status;
+ pthread_join (threads[i], &status);
+ }
+
+ printf ("parent ");
+ for (i = 0; i < THREADS; i ++)
+ printf (ADDR_FMT " ", ADDR_PRINTF (activities[i]));
+ printf ("\n");
+
+ for (i = 0; i < ITERATIONS; i ++)
+ {
+ int j;
+
+ 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 ("\n");
+ }
+
+ printf ("Done!\n");
+
+ return 0;
+}
diff --git a/benchmarks/boehm-gc/ChangeLog b/benchmarks/boehm-gc/ChangeLog
new file mode 100644
index 0000000..bcd3436
--- /dev/null
+++ b/benchmarks/boehm-gc/ChangeLog
@@ -0,0 +1,6 @@
+2008-05-30 Neal H. Walfield <neal@gnu.org>
+
+ * Makefile.am: New file.
+ * pathches: New directory.
+ * patches/01-gc-include-private-gcconfig-h.patch: New file.
+ * patches/02-gc-mach_dep-c.patch: New file.
diff --git a/benchmarks/boehm-gc/Makefile.am b/benchmarks/boehm-gc/Makefile.am
new file mode 100644
index 0000000..872992f
--- /dev/null
+++ b/benchmarks/boehm-gc/Makefile.am
@@ -0,0 +1,117 @@
+# Makefile.am - Makefile template for the Boehm GC
+# Copyright (C) 2008 Free Software Foundation, Inc.
+# Written by Neal H. Walfield
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+include $(top_srcdir)/Makefoo.am
+
+noinst_LIBRARIES = libgc.a
+
+# Patches to apply to the source tree.
+patch_files = 01-gc-include-private-gcconfig-h.patch \
+ 02-gc-mach_dep-c.patch
+
+# Files to link into newlib's source tree (relative to $(srcdir)/addon)
+addon =
+
+EXTRA_DIST = $(addprefix patches/, $(patch_files)) \
+ $(addprefix addon/, $(addon))
+
+# The source tarball.
+gc_tarball = gc-7.0.tar.gz
+gc_snapshot = $(gc_tarball)
+
+# Grab the snapshot
+$(srcdir)/$(gc_tarball):
+ wget $(gc_snapshot) -O $(srcdir)/$(gc_tarball)
+
+# Extract it.
+$(srcdir)/gc/unpack.stamp: $(srcdir)/$(gc_tarball)
+ if test -e $(srcdir)/gc/.; then \
+ echo "Refusing to extract over $(srcdir)/gc"; \
+ exit 1; \
+ fi
+ ( cd $(srcdir) \
+ && tar xfvz $(gc_tarball) \
+ && mv $(subst .tar.gz,,$(gc_tarball)) gc )
+ touch $@
+
+# Apply any local patches. (Revert any applied older version.)
+$(addprefix $(srcdir)/gc/,$(addsuffix .applied,$(patch_files))): $(srcdir)/gc/unpack.stamp
+$(addprefix $(srcdir)/gc/,$(addsuffix .applied,$(patch_files))): $(srcdir)/gc/%.applied: $(srcdir)/patches/%
+ if test -e "$@"; \
+ then \
+ ( cd $(srcdir)/gc && sh /dev/stdin -R ) < $@ && rm -f $@; \
+ fi
+ ( cd $(srcdir)/gc && sh /dev/stdin ) < $<
+ cp $< $@
+
+rpatch:
+ for p in $(shell tac -s ' ' $(patch_files)) ; do \
+ (cd $(srcdir)/gc; sh ../$(srcdir)/$${p} -R) || exit 1 ; \
+ done
+
+# Link the addon files into the source tree.
+$(addprefix $(srcdir)/gc/, $(addon)): $(srcdir)/gc/unpack.stamp
+$(addprefix $(srcdir)/gc/, $(addon)): $(srcdir)/gc/%: $(srcdir)/addon/%
+ mkdir -p $(dir $@)
+ $(LN_S) -f $(abspath $<) $@
+# Touch the file, as Make follows symlinks, the source file for sure is younger
+# than the unpack.stamp and thus those files will get linked again and again.
+ touch $@
+
+$(srcdir)/gc/patch.stamp: $(srcdir)/gc/unpack.stamp \
+ $(addprefix $(srcdir)/gc/,$(addsuffix .applied,$(patch_files))) \
+ $(addprefix $(srcdir)/gc/,$(addon))
+ cd $(srcdir)/gc/ \
+ && $(fix_config_guess_and_sub) \
+ && autoreconf
+ touch $@
+
+gc-build/configure-stamp: $(srcdir)/gc/patch.stamp Makefile.am
+ ( cd gc && $(fix_config_guess_and_sub) && autoreconf )
+ rm -rf gc-build
+ mkdir gc-build
+ (cd gc-build && $(srcdir)/gc/configure \
+ CPPFLAGS="$(USER_CPPFLAGS)" \
+ CFLAGS='$(USER_CFLAGS)' \
+ LDFLAGS='$(USER_LDFLAGS)' \
+ EXTRA_TEST_LIBS='$(USER_LDADD)' \
+ --disable-shared --disable-threads \
+ --disable-java-finalization --disable-gcj-support \
+ --prefix=$(abs_builddir)/gc-install \
+ --build=$(build_alias) --host=$(host_alias))
+ touch $@
+
+gc-build/build-stamp: gc-build/configure-stamp
+ cd gc-build && \
+ make all gctest install
+ touch $@
+
+libgc.a: gc-build/build-stamp
+ $(LN_S) -f gc-build/.libs/libgc.a .
+
+clean-local:
+ rm -rf gc-build
+ rm -rf gc-install
+
+CLEANFILES = include
+
+DISTCLEANFILES = $(srcdir)/$(gc_tarball) \
+ gc-configure-stamp
+
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
new file mode 100644
index 0000000..9772e59
--- /dev/null
+++ b/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch
@@ -0,0 +1,17 @@
+#! /bin/sh
+patch -p1 -f $* < $0
+exit $?
+
+Tweak the configuration.
+
+--- gc/include/private/gcconfig.h~ 2007-06-29 02:00:09.000000000 +0200
++++ gc/include/private/gcconfig.h 2008-02-21 17:08:20.000000000 +0100
+@@ -1275,7 +1275,7 @@
+ extern int _end[];
+ # define DATAEND ((ptr_t) (_end))
+ /* # define MPROTECT_VDB Not quite working yet? */
+-# define DYNAMIC_LOADING
++# undef DYNAMIC_LOADING
+ # endif
+ # ifdef DARWIN
+ # define OS_TYPE "DARWIN"
diff --git a/benchmarks/boehm-gc/patches/02-gc-mach_dep-c.patch b/benchmarks/boehm-gc/patches/02-gc-mach_dep-c.patch
new file mode 100644
index 0000000..6c24087
--- /dev/null
+++ b/benchmarks/boehm-gc/patches/02-gc-mach_dep-c.patch
@@ -0,0 +1,18 @@
+#! /bin/sh
+patch -p1 -f $* < $0
+exit $?
+
+Prefer use of setjmp to use of getcontext.
+
+--- gc/mach_dep.c~ 2007-07-02 19:07:21.000000000 +0200
++++ gc/mach_dep.c 2008-02-29 15:13:39.000000000 +0100
+@@ -174,7 +174,7 @@ void GC_with_callee_saves_pushed(void (*
+
+ # if defined(HAVE_PUSH_REGS)
+ GC_push_regs();
+-# elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32)
++# elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32) && !defined(HURD)
+ /* Older versions of Darwin seem to lack getcontext(). */
+ /* ARM Linux often doesn't support a real getcontext(). */
+ ucontext_t ctxt;
+
diff --git a/benchmarks/shared-memory-distribution.c b/benchmarks/shared-memory-distribution.c
new file mode 100644
index 0000000..22a046a
--- /dev/null
+++ b/benchmarks/shared-memory-distribution.c
@@ -0,0 +1,148 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <hurd/activity.h>
+#include <hurd/storage.h>
+#include <hurd/startup.h>
+
+static addr_t activity;
+
+/* Initialized by the machine-specific startup-code. */
+extern struct hurd_startup_data *__hurd_startup_data;
+
+int
+main (int argc, char *argv[])
+{
+ extern int output_debug;
+ output_debug = 1;
+
+ activity = __hurd_startup_data->activity;
+
+#define PAGES 1000
+
+ /* Allocate the buffer. */
+ void *buffer = mmap (0, PAGESIZE * PAGES, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (buffer == MAP_FAILED)
+ {
+ printf ("Failed to allocate memory: %s\n", strerror (errno));
+ return 1;
+ }
+
+#define THREADS 3
+ /* And the activities. */
+ addr_t activities[THREADS];
+
+ int i;
+ for (i = 0; i < THREADS; i ++)
+ activities[i] = storage_alloc (activity, cap_activity,
+ STORAGE_LONG_LIVED,
+ OBJECT_POLICY_DEFAULT,
+ ADDR_VOID).addr;
+
+ bool terminate = false;
+ l4_thread_id_t tids[THREADS];
+ for (i = 0; i < THREADS; i ++)
+ tids[i] = l4_nilthread;
+
+ void *worker (void *arg)
+ {
+ int w = (intptr_t) arg;
+
+ tids[w] = l4_myself ();
+
+ pthread_setactivity_np (activities[w]);
+
+ uintptr_t t = 0;
+ 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);
+
+ l4_thread_switch (tids[rand () % THREADS]);
+ }
+
+ printf ("Thread %d: %d operations\n", w, count);
+
+ /* We need to return t, otherwise, the above loop will be
+ optimized away. */
+ return (void *) t;
+ }
+
+ /* Start the threads. */
+ pthread_t threads[THREADS];
+
+ error_t err;
+ for (i = 0; i < THREADS; i ++)
+ {
+ err = pthread_create (&threads[i], NULL, worker, (intptr_t) i);
+ if (err)
+ printf ("Failed to create thread: %s\n", strerror (errno));
+ }
+
+#define ITERATIONS 100
+ struct activity_stats stats[ITERATIONS][1 + THREADS];
+
+ uintptr_t next_period = 0;
+ for (i = 0; i < ITERATIONS; i ++)
+ {
+ debug (0, DEBUG_BOLD ("starting iteration %d (%x)"), i, l4_myself ());
+
+ int count;
+ struct activity_stats_buffer buffer;
+
+ rm_activity_stats (activity, next_period, &buffer, &count);
+ assert (count > 0);
+ if (i != 0)
+ assert (buffer.stats[0].period != stats[i - 1][0].period);
+
+ stats[i][0] = buffer.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];
+ }
+
+ next_period = buffer.stats[0].period + 1;
+ }
+
+ terminate = true;
+ for (i = 0; i < THREADS; i ++)
+ {
+ void *status;
+ pthread_join (threads[i], &status);
+ }
+
+ printf ("parent ");
+ for (i = 0; i < THREADS; i ++)
+ printf (ADDR_FMT " ", ADDR_PRINTF (activities[i]));
+ printf ("\n");
+
+ for (i = 0; i < ITERATIONS; i ++)
+ {
+ int j;
+
+ 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 ("\n");
+ }
+
+ printf ("Done!\n");
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index 4a777b6..3897206 100644
--- a/configure.ac
+++ b/configure.ac
@@ -296,6 +296,8 @@ AC_CONFIG_FILES([Makefile
newlib/Makefile
hieronymus/Makefile
ruth/Makefile
+ benchmarks/Makefile
+ benchmarks/boehm-gc/Makefile
doc/Makefile
])
AC_OUTPUT