diff -urN /usr/src/sys/conf/files src/sys/conf/files --- /usr/src/sys/conf/files Wed Jul 20 00:40:13 2005 +++ src/sys/conf/files Sat Jul 23 10:44:20 2005 @@ -1784,6 +1784,9 @@ security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test +test/test.c standard +test/test_mem_timing.c standard +test/test_synch_timing.c standard ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs diff -urN /usr/src/sys/kern/kern_sx.c src/sys/kern/kern_sx.c --- /usr/src/sys/kern/kern_sx.c Fri Jan 7 00:35:39 2005 +++ src/sys/kern/kern_sx.c Fri Jul 22 23:32:41 2005 @@ -71,7 +71,10 @@ ("sx lock %s %p already initialized", description, sx)); bzero(sx, sizeof(*sx)); lock->lo_class = &lock_class_sx; - lock->lo_type = lock->lo_name = description; + lock->lo_name = description; +#ifdef WITNESS + lock->lo_type = description; +#endif lock->lo_flags = LO_WITNESS | LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE; sx->sx_lock = mtx_pool_find(mtxpool_lockbuilder, sx); diff -urN /usr/src/sys/kern/subr_witness.c src/sys/kern/subr_witness.c --- /usr/src/sys/kern/subr_witness.c Sun Jun 5 01:24:50 2005 +++ src/sys/kern/subr_witness.c Sat Jul 23 00:19:29 2005 @@ -1987,4 +1987,16 @@ witness_display(db_printf); } + +DB_SHOW_COMMAND(alllox, db_witness_alllox) +{ + struct lock_object *lock; + + printf("lock\taddr\ttype\tflags\n"); + TAILQ_FOREACH(lock, &all_locks, lo_list) { + printf("%s\t%p\t%s\t%x\n", lock->lo_name, lock, lock->lo_type, + lock->lo_flags); + } +} + #endif diff -urN /usr/src/sys/test/test.c src/sys/test/test.c --- /usr/src/sys/test/test.c Thu Jan 1 01:00:00 1970 +++ src/sys/test/test.c Sat Jul 23 10:40:09 2005 @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2005 Robert N. M. Watson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS QUADERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define ITERATIONS 2048 +const int test_iterations = ITERATIONS; + +SYSCTL_NODE(, OID_AUTO, test, CTLFLAG_RD, NULL, "test tree"); + +SYSCTL_INT(_test, OID_AUTO, iterations, CTLFLAG_RD, + __DECONST(int *, &test_iterations), 0, "Number of iterations in a test"); + +u_int64_t loop_cost; + +static __inline void +test_stub(void) +{ + + /* Nothing. */ +} + +static int +sysctl_test_stub_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_stub(); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + loop_cost = i; + i /= test_iterations; + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, stub_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_stub_timing, "I", "Timing for stub test"); diff -urN /usr/src/sys/test/test.h src/sys/test/test.h --- /usr/src/sys/test/test.h Thu Jan 1 01:00:00 1970 +++ src/sys/test/test.h Sat Jul 23 10:40:31 2005 @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2005 Robert N. M. Watson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TEST_TEST_H_ +#define _TEST_TEST_H_ + +SYSCTL_DECL(_test); + +extern u_int64_t loop_cost; +extern const int test_iterations; + +#endif /* !_TEST_TEST_H_ */ diff -urN /usr/src/sys/test/test_mem_timing.c src/sys/test/test_mem_timing.c --- /usr/src/sys/test/test_mem_timing.c Thu Jan 1 01:00:00 1970 +++ src/sys/test/test_mem_timing.c Sat Jul 23 10:40:45 2005 @@ -0,0 +1,181 @@ +/*- + * Copyright (c) 2005 Robert N. M. Watson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS QUADERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +static uma_zone_t testmem_zone; + +static void +testmem_start(void *arg) +{ + + testmem_zone = uma_zcreate("testmem_zone", sizeof(void *), NULL, NULL, + NULL, NULL, UMA_ALIGN_PTR, 0); +} +SYSINIT(testmem, SI_SUB_KMEM, SI_ORDER_ANY, testmem_start, NULL); + +MALLOC_DEFINE(M_TEST, "testmem", "testmem memory"); + +/* + * Test for UMA cached zalloc/zfree of minimally sized memory. + */ +static __inline void +test_zalloc(void) +{ + void *dummy; + + dummy = uma_zalloc(testmem_zone, M_WAITOK); + uma_zfree(testmem_zone, dummy); +} + +static int +sysctl_test_zalloc_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + void *dummy; + + /* + * Warm the per-cpu cache before beginning the test. + */ + dummy = uma_zalloc(testmem_zone, M_WAITOK); + uma_zfree(testmem_zone, dummy); + + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_zalloc(); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + if (loop_cost > i) + i = 0; + else + i -= loop_cost; + i /= test_iterations; + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, zalloc_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_zalloc_timing, "I", "Timing for cached zalloc+zfree"); + +/* + * Test for malloc/free of minimally sized memory. + */ +static __inline void +test_malloc(void) +{ + void *dummy; + + dummy = malloc(sizeof(void *), M_TEST, M_WAITOK); + free(dummy, M_TEST); +} + +static int +sysctl_test_malloc_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + void *dummy; + + /* + * Warm the per-cpu cache before beginning the test. + */ + dummy = malloc(sizeof(void *), M_TEST, M_WAITOK); + free(dummy, M_TEST); + + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_malloc(); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + if (loop_cost > i) + i = 0; + else + i -= loop_cost; + i /= test_iterations; + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, malloc_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_malloc_timing, "I", "Timing for cached malloc+free"); + + +/* + * Test for MGET()/m_free() of a single data mbuf. + */ +static __inline void +test_mbuf(void) +{ + struct mbuf *m; + + MGET(m, M_TRYWAIT, MT_DATA); + m_free(m); +} + +static int +sysctl_test_mbuf_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + struct mbuf *m; + u_int64_t i; + + /* + * Warm the per-cpu cache before beginning the test. + */ + MGET(m, M_TRYWAIT, MT_DATA); + m_free(m); + + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_mbuf(); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + if (loop_cost > i) + i = 0; + else + i -= loop_cost; + i /= test_iterations; + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, mbuf_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_mbuf_timing, "I", "Timing for cached MGET/mfree"); diff -urN /usr/src/sys/test/test_synch_timing.c src/sys/test/test_synch_timing.c --- /usr/src/sys/test/test_synch_timing.c Thu Jan 1 01:00:00 1970 +++ src/sys/test/test_synch_timing.c Sat Jul 23 18:50:38 2005 @@ -0,0 +1,425 @@ +/*- + * Copyright (c) 2004-2005 Robert N. M. Watson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS QUADERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +int time[2048]; + +static int j; +static __inline void +test_atomicintadd(void) +{ + + atomic_add_int(&j, 1); +} + +static int +sysctl_test_atomicint_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + test_atomicintadd(); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, atomicint_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_atomicint_timing, "I", "Timing for atomic integers"); + +static __inline void +test_intadd(void) +{ + + j++; +} + +static int +sysctl_test_int_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + test_intadd(); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, int_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_int_timing, "I", "Timing for non-atomic integers"); + +static __inline void +test_critical(void) +{ + + critical_enter(); + critical_exit(); +} + +static int +sysctl_test_critical_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + test_critical(); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, critical_timing, CTLTYPE_QUAD | CTLFLAG_RW, + 0, 0, sysctl_test_critical_timing, "I", "Timing for critical sections"); + +static __inline void +test_sleep_mutex(struct mtx *mutex) +{ + + mtx_lock(mutex); + mtx_unlock(mutex); +} + +static int +sysctl_test_sleep_mutex_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + struct mtx mutex; + + bzero(&mutex, sizeof(mutex)); + mtx_init(&mutex, "mutex", NULL, MTX_DEF); + + critical_enter(); + mtx_lock_spin(&sched_lock); + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + mtx_lock(&mutex); + mtx_unlock(&mutex); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + mtx_unlock_spin(&sched_lock); + critical_exit(); + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, sleep_mutex_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_sleep_mutex_timing, "I", "Timing for sleep mutexes"); + +static __inline void +test_spin_mutex(struct mtx *mutex) +{ + + mtx_lock_spin(mutex); + mtx_unlock_spin(mutex); +} + +static int +sysctl_test_spin_mutex_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + struct mtx mutex; + + bzero(&mutex, sizeof(struct mtx)); + mtx_init(&mutex, "mtx", NULL, MTX_SPIN); + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + test_spin_mutex(&mutex); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, spin_mutex_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_spin_mutex_timing, "I", "Timing for spin mutexes"); + +static __inline void +test_exclusive_sx(struct sx *sx) +{ + + sx_xlock(sx); + sx_xunlock(sx); +} + +static int +sysctl_test_exclusive_sx_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + struct sx sx; + u_int64_t i; + + bzero(&sx, sizeof(sx)); + sx_init(&sx, "sx"); + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_exclusive_sx(&sx); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + i -= loop_cost; + i /= test_iterations; + sx_destroy(&sx); + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, exclusive_sx_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_exclusive_sx_timing, "I", "Timing for xlock sx"); + +static __inline void +test_shared_sx(struct sx *sx) +{ + + sx_slock(sx); + sx_sunlock(sx); +} + +static int +sysctl_test_shared_sx_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + struct sx sx; + u_int64_t i; + + bzero(&sx, sizeof(sx)); + sx_init(&sx, "sx"); + start_cycles = get_cyclecount(); + for (i = 0; i < test_iterations; i++) + test_shared_sx(&sx); + stop_cycles = get_cyclecount(); + i = stop_cycles - start_cycles; + i -= loop_cost; + i /= test_iterations; + sx_destroy(&sx); + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, shared_sx_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_shared_sx_timing, "I", "Timing for xlock sx"); + +static __inline void +test_intr(void) +{ + register_t saved_flags; + + saved_flags = intr_disable(); + intr_restore(saved_flags); +} + +static int +sysctl_test_intr_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + test_intr(); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, intr_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_intr_timing, "I", "Timing for disabling/restoring interrupts"); + +#if 0 +static __inline void +test_contested_sleep_mtx(struct mtx *mutex) +{ + mtx_lock(mutex); + mtx_unlock(mutex); +} + +int run = 1; +static struct mtx mutex; +static struct proc *mtx_proc = NULL; + +static void +mtx_content(void __unused *arg) +{ + volatile int i; + + for (;;) { + if (run) { + tsleep(&mutex, PDROP | curthread->td_priority, "mtx", + 0); + run = 0; + } + mtx_lock(&mutex); + for(i = 0; i < 2048; i++); + mtx_lock_spin(&sched_lock); + mi_switch(SW_VOL, NULL); + mtx_unlock_spin(&sched_lock); + mtx_unlock(&mutex); + } +} + +static int +sysctl_test_contested_sleep_mtx_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + + if (!mtx_proc) { + bzero(&mutex, sizeof(struct mtx)); + mtx_init(&mutex, "mutex", NULL, MTX_DEF); + error = kthread_create(mtx_content, NULL, &mtx_proc, RFSTOPPED, + 0, "mtx_cont"); + if (error) { + printf("couldn't start mutex contention thread: %d\n", error); + return (error); + } + setrunqueue(FIRST_THREAD_IN_PROC(mtx_proc), SRQ_BORING); + } + + start_cycles = get_cyclecount(); + run = 0; + wakeup(&mutex); + for (i = 0; i < test_iterations; i++) + test_contested_sleep_mtx(&mutex); + stop_cycles = get_cyclecount(); + run = 1; + i = stop_cycles - start_cycles; + i -= loop_cost; + i /= test_iterations; + + return (sysctl_handle_int(oidp, &i, sizeof(i), req)); +} + +SYSCTL_PROC(_test, OID_AUTO, contested_sleep_mutex_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_contested_sleep_mtx_timing, "I", "Timing for contested sleep mutex"); +#endif + +static int +test_call(int *i) +{ + i++; + return (int)i; +} + +static int +sysctl_test_call_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error, j; + + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + j = test_call(&j); + stop_cycles = get_cyclecount(); + time[i] = stop_cycles - start_cycles; + } + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, call_timing, CTLTYPE_QUAD | CTLFLAG_RW, + NULL, 0, sysctl_test_call_timing, "I", "Timing for a function call"); + + +static int +sysctl_test_mem_timing(SYSCTL_HANDLER_ARGS) +{ + u_int64_t start_cycles, stop_cycles; + u_int64_t i; + int error; + struct mtx mutex; + + bzero(&mutex, sizeof(mutex)); + mtx_init(&mutex, "mutex", NULL, MTX_SPIN); + + critical_enter(); + mtx_lock_spin(&sched_lock); + for (i = 0; i < test_iterations; i++) { + start_cycles = get_cyclecount(); + mtx_lock_spin(&mutex); + stop_cycles = get_cyclecount(); + mtx_unlock_spin(&mutex); + time[i] = stop_cycles - start_cycles; + } + mtx_unlock_spin(&sched_lock); + critical_exit(); + + error = SYSCTL_OUT(req, time, test_iterations); + return (error); +} + +SYSCTL_PROC(_test, OID_AUTO, mem_timing, CTLTYPE_OPAQUE | CTLFLAG_RD, + NULL, 0, sysctl_test_mem_timing, "I", "Timing for memory access");