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 /test | |
parent | c204a2eacf870a05f1ccde63e4da452017b6e2f5 (diff) |
test/test_sref_weakref: new test module
Diffstat (limited to 'test')
-rw-r--r-- | test/test_sref_weakref.c | 118 |
1 files changed, 118 insertions, 0 deletions
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"); +} |