summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2011-09-23 14:47:59 +0400
committerIvan Maidanski <ivmai@mail.ru>2011-09-23 14:47:59 +0400
commit33d8645dc6a2c1c130f0c334e2d51c3f8c5b0de8 (patch)
tree585dcd2dc4d9f06bf1b8f446a28e46b7c0f48c9a /tests
parent2aa783260816855e59fe3244658e7c2b2e2cea6e (diff)
parent831e2f2123539ce464a1a8b4c328c9275db2b6da (diff)
downloadbdwgc-33d8645dc6a2c1c130f0c334e2d51c3f8c5b0de8.tar.gz
Merge remote-tracking branch 'remotes/paurkedal/t/disclaim-pullreq' into paurkedal-disclaim-v2
Diffstat (limited to 'tests')
-rw-r--r--tests/disclaim_bench.c130
-rw-r--r--tests/disclaim_test.c166
-rw-r--r--tests/tests.am11
3 files changed, 307 insertions, 0 deletions
diff --git a/tests/disclaim_bench.c b/tests/disclaim_bench.c
new file mode 100644
index 00000000..2bdcaac8
--- /dev/null
+++ b/tests/disclaim_bench.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <time.h> // FIXME: It would be good not to use timing API by
+ // default (is it is not quite portable).
+
+#include "atomic_ops.h"
+#include "gc_disclaim.h"
+
+static AO_t free_count = 0;
+
+typedef struct testobj_s *testobj_t;
+struct testobj_s {
+ testobj_t keep_link;
+ int i;
+};
+
+void testobj_finalize(void *obj, void *carg)
+{
+ AO_fetch_and_add1((AO_t *)carg);
+ assert(((testobj_t)obj)->i++ == 109);
+}
+
+static struct GC_finalizer_closure fclos = {
+ testobj_finalize,
+ &free_count
+};
+
+testobj_t testobj_new(int model)
+{
+ testobj_t obj;
+ switch (model) {
+ case 0:
+ obj = GC_MALLOC(sizeof(struct testobj_s));
+ GC_register_finalizer_no_order(obj, testobj_finalize, &free_count,
+ NULL, NULL);
+ break;
+ case 1:
+ obj = GC_finalized_malloc(sizeof(struct testobj_s), &fclos);
+ break;
+ case 2:
+ obj = GC_MALLOC(sizeof(struct testobj_s));
+ break;
+ default:
+ exit(-1);
+ }
+ assert(obj->i == 0 && obj->keep_link == NULL);
+ obj->i = 109;
+ return obj;
+}
+
+#define ALLOC_CNT (4*1024*1024)
+#define KEEP_CNT (32*1024)
+
+static char const *model_str[3] = {
+ "regular finalization",
+ "finalize on reclaim",
+ "no finalization"
+};
+
+int main(int argc, char **argv)
+{
+ int i;
+ int model;
+ testobj_t *keep_arr;
+ double t;
+
+ GC_INIT();
+ GC_init_finalized_malloc();
+
+ keep_arr = GC_MALLOC(sizeof(void *)*KEEP_CNT);
+
+ if (argc == 1) {
+ char *buf = GC_MALLOC(strlen(argv[0]) + 3);
+ printf("\t\t\tfin. ratio time/s time/fin.\n");
+ fflush(stdout);
+ for (i = 0; i < 3; ++i) {
+ int st;
+ sprintf(buf, "%s %d", argv[0], i);
+ st = system(buf); // FIXME: is this available on all targets?
+ if (st != 0)
+ return st;
+ }
+ return 0;
+ }
+ if (argc == 2 && strcmp(argv[1], "--help") == 0) {
+ fprintf(stderr,
+ "Usage: %s FINALIZATION_MODEL\n"
+ "\t0 -- original finalization\n"
+ "\t1 -- finalization on reclaim\n"
+ "\t2 -- no finalization\n", argv[0]);
+ return 1;
+ }
+ model = atoi(argv[1]);
+ if (model < 0 || model > 2)
+ exit(2);
+ t = -(double)clock();
+ for (i = 0; i < ALLOC_CNT; ++i) {
+ int k = rand() % KEEP_CNT;
+ keep_arr[k] = testobj_new(model);
+ }
+
+ GC_gcollect();
+
+ t += clock();
+ t /= CLOCKS_PER_SEC;
+ if (model < 2)
+ printf("%20s: %12.4lf %12lg %12lg\n", model_str[model],
+ free_count/(double)ALLOC_CNT, t, t/free_count);
+ else
+ printf("%20s: %12.4lf %12lg %12s\n",
+ model_str[model], 0.0, t, "N/A");
+ return 0;
+}
diff --git a/tests/disclaim_test.c b/tests/disclaim_test.c
new file mode 100644
index 00000000..4bd4a1d2
--- /dev/null
+++ b/tests/disclaim_test.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/* Test that objects reachable from an object allocated with */
+/* GC_malloc_with_finalizer is not reclaimable before the finalizer */
+/* is called. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gc_disclaim.h"
+
+typedef struct pair_s *pair_t;
+
+struct pair_s {
+ int is_valid;
+ int checksum;
+ pair_t car;
+ pair_t cdr;
+};
+
+void pair_dct(void *obj, void *cd)
+{
+ pair_t p = obj;
+ int checksum;
+
+ /* Check that obj and its car and cdr are not trashed. */
+# ifdef DEBUG_DISCLAIM_DESTRUCT
+ printf("Destruct %p = (%p, %p)\n", p, p->car, p->cdr);
+# endif
+ assert(GC_base(obj));
+ assert(p->is_valid);
+ assert(!p->car || p->car->is_valid);
+ assert(!p->cdr || p->cdr->is_valid);
+ checksum = 782;
+ if (p->car) checksum += p->car->checksum;
+ if (p->cdr) checksum += p->cdr->checksum;
+ assert(p->checksum == checksum);
+
+ /* Invalidate it. */
+ p->is_valid = 0;
+ p->checksum = 0;
+ p->car = NULL;
+ p->cdr = NULL;
+}
+
+pair_t
+pair_new(pair_t car, pair_t cdr)
+{
+ pair_t p;
+ static struct GC_finalizer_closure fc = { pair_dct, NULL };
+
+ p = GC_finalized_malloc(sizeof(struct pair_s), &fc);
+ p->is_valid = 1;
+ p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0);
+ p->car = car;
+ p->cdr = cdr;
+# ifdef DEBUG_DISCLAIM_DESTRUCT
+ printf("Construct %p = (%p, %p)\n", p, p->car, p->cdr);
+# endif
+ return p;
+}
+
+void
+pair_check_rec(pair_t p)
+{
+ while (p) {
+ int checksum = 782;
+ if (p->car) checksum += p->car->checksum;
+ if (p->cdr) checksum += p->cdr->checksum;
+ assert(p->checksum == checksum);
+ if (rand() % 2)
+ p = p->car;
+ else
+ p = p->cdr;
+ }
+}
+
+#ifdef GC_PTHREADS
+# define THREAD_CNT 6
+#else
+# define THREAD_CNT 1
+#endif
+
+#define POP_SIZE 1000
+#if THREAD_CNT > 1
+# define MUTATE_CNT 2000000/THREAD_CNT
+#else
+# define MUTATE_CNT 10000000
+#endif
+#define GROW_LIMIT 10000000
+
+void *test(void *data)
+{
+ int i;
+ pair_t pop[POP_SIZE];
+ memset(pop, 0, sizeof(pop));
+ for (i = 0; i < MUTATE_CNT; ++i) {
+ int t = rand() % POP_SIZE;
+ switch (rand() % (i > GROW_LIMIT? 5 : 3)) {
+ case 0: case 3:
+ if (pop[t])
+ pop[t] = pop[t]->car;
+ break;
+ case 1: case 4:
+ if (pop[t])
+ pop[t] = pop[t]->cdr;
+ break;
+ case 2:
+ pop[t] = pair_new(pop[rand() % POP_SIZE],
+ pop[rand() % POP_SIZE]);
+ break;
+ }
+ if (rand() % 8 == 1)
+ pair_check_rec(pop[rand() % POP_SIZE]);
+ }
+ return 0;
+}
+
+int main(void)
+{
+#if THREAD_CNT > 1
+ pthread_t th[THREAD_CNT];
+ int i;
+#endif
+
+ GC_INIT();
+ GC_init_finalized_malloc();
+
+#if THREAD_CNT > 1
+ printf("Threaded disclaim test.\n");
+ for (i = 0; i < THREAD_CNT; ++i) {
+ int err = GC_pthread_create(&th[i], NULL, test, NULL);
+ if (err) {
+ fprintf(stderr, "Failed to create thread # %d: %s\n", i,
+ strerror(err));
+ exit(1);
+ }
+ }
+ for (i = 0; i < THREAD_CNT; ++i) {
+ int err = GC_pthread_join(th[i], NULL);
+ if (err) {
+ fprintf(stderr, "Failed to join thread # %d: %s\n", i,
+ strerror(err));
+ exit(69);
+ }
+ }
+#else
+ printf("Unthreaded disclaim test.\n");
+ test(NULL);
+#endif
+ return 0;
+}
diff --git a/tests/tests.am b/tests/tests.am
index 13647b3a..9685ae67 100644
--- a/tests/tests.am
+++ b/tests/tests.am
@@ -91,3 +91,14 @@ else
test_cpp_LDADD = libgccpp.la $(test_ldadd)
endif
endif
+
+if ENABLE_DISCLAIM
+TESTS += disclaim_test
+check_PROGRAMS += disclaim_test
+disclaim_test_SOURCES = tests/disclaim_test.c
+disclaim_test_LDADD = $(test_ldadd)
+TESTS += disclaim_bench
+check_PROGRAMS += disclaim_bench
+disclaim_bench_SOURCES = tests/disclaim_bench.c
+disclaim_bench_LDADD = $(test_ldadd)
+endif