summaryrefslogtreecommitdiff
path: root/benchmarks/activity-distribution.c
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks/activity-distribution.c')
-rw-r--r--benchmarks/activity-distribution.c203
1 files changed, 203 insertions, 0 deletions
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;
+}