diff options
author | Richard Braun <rbraun@sceen.net> | 2017-01-25 00:37:04 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-01-25 00:43:57 +0100 |
commit | 163b6179c27dbc7f38915e3756bfa35e6092c43d (patch) | |
tree | 3e8e863ea88c05a1acb037bf64096e48b3ad7528 | |
parent | c204a2eacf870a05f1ccde63e4da452017b6e2f5 (diff) |
test/test_sref_weakref: new test module
-rw-r--r-- | Makefrag.am | 12 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | test/test_sref_weakref.c | 118 |
3 files changed, 129 insertions, 4 deletions
diff --git a/Makefrag.am b/Makefrag.am index b0a5d32b..4ac5cef1 100644 --- a/Makefrag.am +++ b/Makefrag.am @@ -90,14 +90,18 @@ if TEST_SREF_DIRTY_ZEROES x15_SOURCES += test/test_sref_dirty_zeroes.c endif TEST_SREF_DIRTY_ZEROES -if TEST_VM_PAGE_FILL -x15_SOURCES += test/test_vm_page_fill.c -endif TEST_VM_PAGE_FILL - if TEST_SREF_NOREF x15_SOURCES += test/test_sref_noref.c endif TEST_SREF_NOREF +if TEST_SREF_WEAKREF +x15_SOURCES += test/test_sref_weakref.c +endif TEST_SREF_WEAKREF + +if TEST_VM_PAGE_FILL +x15_SOURCES += test/test_vm_page_fill.c +endif TEST_VM_PAGE_FILL + if TEST_X86_DOUBLE_FAULT x15_SOURCES += test/test_x86_double_fault.c endif TEST_X86_DOUBLE_FAULT diff --git a/configure.ac b/configure.ac index 9c130ed6..023140bd 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ m4_define([ENABLE_TEST_MODULE], [pmap_update_mp], [test_pmap_update_mp=yes], [sref_dirty_zeroes], [test_sref_dirty_zeroes=yes], [sref_noref], [test_sref_noref=yes], + [sref_weakref], [test_sref_weakref=yes], [vm_page_fill], [test_vm_page_fill=yes], [x86_double_fault], [test_x86_double_fault=yes], [xcall], [test_xcall=yes], @@ -60,6 +61,8 @@ AM_CONDITIONAL([TEST_SREF_DIRTY_ZEROES], [test x"$test_sref_dirty_zeroes" = xyes]) AM_CONDITIONAL([TEST_SREF_NOREF], [test x"$test_sref_noref" = xyes]) +AM_CONDITIONAL([TEST_SREF_WEAKREF], + [test x"$test_sref_weakref" = xyes]) AM_CONDITIONAL([TEST_VM_PAGE_FILL], [test x"$test_vm_page_fill" = xyes]) AM_CONDITIONAL([TEST_X86_DOUBLE_FAULT], diff --git a/test/test_sref_weakref.c b/test/test_sref_weakref.c new file mode 100644 index 00000000..079eeaf8 --- /dev/null +++ b/test/test_sref_weakref.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2017 Richard Braun. + * + * This program 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. + * + * This program 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/>. + * + * + * This module is a stress test of the weak reference implementation + * of scalable reference counters. Two threads are created. The first + * periodically allocates a page and initializes a counter inside the + * page, then immediately decrements the counter. The intended effect + * is to mark the counter as dying as soon as possible. The second + * thread continually attempts to obtain a reference, i.e. increment + * the counter, through a weak reference. Counters are regularly + * printed to monitor activity. There should be almost as many noref + * calls as there are iterations in the first thread (a bit lower + * because of the review delay) and a good amount of revives (at least + * on multiprocessor machines) caused by successfully getting the counter + * from the weak reference while it is marked dying but still in review. + * Iterations in the second thread may spike when obtaining a reference + * fails, because the error case is much faster and continues until the + * first thread reinitializes the weak reference. + */ + +#include <kern/error.h> +#include <kern/evcnt.h> +#include <kern/macros.h> +#include <kern/sref.h> +#include <kern/stddef.h> +#include <kern/thread.h> +#include <test/test.h> +#include <vm/vm_kmem.h> + +static struct sref_weakref test_weakref; + +static void +test_noref(struct sref_counter *counter) +{ + vm_kmem_free(counter, sizeof(*counter)); +} + +static void +test_run(void *arg) +{ + struct sref_counter *counter; + volatile unsigned long j; + unsigned long i; + + (void)arg; + + for (i = 1; /* no condition */; i++) { + counter = vm_kmem_alloc(sizeof(*counter)); + + if (counter == NULL) { + continue; + } + + sref_counter_init(counter, &test_weakref, test_noref); + sref_counter_dec(counter); + + for (j = 0; j < 0x20000000; j++); + + printk("run: iterations: %lu\n", i); + evcnt_info("sref_epoch"); + evcnt_info("sref_dirty_zero"); + evcnt_info("sref_revive"); + evcnt_info("sref_true_zero"); + } +} + +static void +test_ref(void *arg) +{ + struct sref_counter *counter; + unsigned long i; + + (void)arg; + + for (i = 1; /* no condition */; i++) { + counter = sref_weakref_get(&test_weakref); + + if (counter != NULL) { + sref_counter_dec(counter); + } + + if ((i % 10000000) == 0) { + printk("ref: iterations: %lu\n", i); + } + } +} + +void +test_setup(void) +{ + struct thread_attr attr; + struct thread *thread; + int error; + + thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_run"); + thread_attr_set_detached(&attr); + error = thread_create(&thread, &attr, test_run, NULL); + error_check(error, "thread_create"); + + thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_ref"); + thread_attr_set_detached(&attr); + error = thread_create(&thread, &attr, test_ref, NULL); + error_check(error, "thread_create"); +} |