Date: Thu, 12 Feb 2009 13:49:52 +0000 (UTC) From: Lawrence Stewart <lstewart@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r188513 - in user/lstewart/alq_varlen_8.x: sys/kern sys/sys tools/test tools/test/alq Message-ID: <200902121349.n1CDnqrJ057249@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: lstewart Date: Thu Feb 12 13:49:51 2009 New Revision: 188513 URL: http://svn.freebsd.org/changeset/base/188513 Log: Checkpoint commit of an alq test harness I'm working on. Added: user/lstewart/alq_varlen_8.x/tools/test/alq/ user/lstewart/alq_varlen_8.x/tools/test/alq/Makefile (contents, props changed) user/lstewart/alq_varlen_8.x/tools/test/alq/alqtest.c (contents, props changed) Modified: user/lstewart/alq_varlen_8.x/sys/kern/kern_alq.c user/lstewart/alq_varlen_8.x/sys/sys/alq.h user/lstewart/alq_varlen_8.x/tools/test/README Modified: user/lstewart/alq_varlen_8.x/sys/kern/kern_alq.c ============================================================================== --- user/lstewart/alq_varlen_8.x/sys/kern/kern_alq.c Thu Feb 12 13:04:13 2009 (r188512) +++ user/lstewart/alq_varlen_8.x/sys/kern/kern_alq.c Thu Feb 12 13:49:51 2009 (r188513) @@ -64,6 +64,7 @@ struct alq { //struct ale *aq_first; /* First ent */ //struct ale *aq_entfree; /* First free ent */ //struct ale *aq_entvalid; /* First ent valid for writing */ + void (*doio_debugcallback)(void); LIST_ENTRY(alq) aq_act; /* List of active queues */ LIST_ENTRY(alq) aq_link; /* List of all queues */ }; @@ -267,7 +268,7 @@ alq_doio(struct alq *alq) int iov; int vfslocked; - KASSERT(alq->aq_freebytes != alq->aq_buflen, + KASSERT((alq->aq_freebytes != alq->aq_buflen), ("%s: queue emtpy!", __func__) ); @@ -300,6 +301,10 @@ alq_doio(struct alq *alq) } alq->aq_flags |= AQ_FLUSHING; + + if (alq->doio_debugcallback != NULL) + alq->doio_debugcallback(); + ALQ_UNLOCK(alq); auio.uio_iov = &aiov[0]; @@ -343,6 +348,9 @@ alq_doio(struct alq *alq) if (alq->aq_freebytes == alq->aq_buflen) alq->aq_writehead = alq->aq_writetail = 0; + if (alq->doio_debugcallback != NULL) + alq->doio_debugcallback(); + if (alq->aq_flags & AQ_WANTED) { alq->aq_flags &= ~AQ_WANTED; return (1); @@ -377,8 +385,8 @@ alq_open(struct alq **alqp, const char * int error; int vfslocked; - KASSERT(size > 0, ("%s: size <= 0", __func__)); - KASSERT(count >= 0, ("%s: count < 0", __func__)); + KASSERT((size > 0), ("%s: size <= 0", __func__)); + KASSERT((count >= 0), ("%s: count < 0", __func__)); *alqp = NULL; td = curthread; @@ -419,6 +427,8 @@ alq_open(struct alq **alqp, const char * alq->aq_writehead = alq->aq_writetail = 0; + alq->doio_debugcallback = NULL; + if ((error = ald_add(alq)) != 0) return (error); *alqp = alq; @@ -434,7 +444,7 @@ int alq_write(struct alq *alq, void *data, int flags) { /* should only be called in fixed length message (legacy) mode */ - KASSERT(alq->aq_entmax > 0 && alq->aq_entlen > 0, + KASSERT((alq->aq_entmax > 0 && alq->aq_entlen > 0), ("%s: fixed length write on variable length queue", __func__) ); return (alq_writen(alq, data, alq->aq_entlen, flags)); @@ -446,7 +456,7 @@ alq_writen(struct alq *alq, void *data, int activate = 0; int copy = len; - KASSERT(len > 0 && len <= alq->aq_buflen, + KASSERT((len > 0 && len <= alq->aq_buflen), ("%s: len <= 0 || len > alq->aq_buflen", __func__) ); @@ -509,7 +519,8 @@ alq_writen(struct alq *alq, void *data, alq->aq_freebytes -= len; - if ((alq->aq_flags & AQ_ACTIVE) == 0) { + if (((alq->aq_flags & AQ_ACTIVE) == 0) && + ((flags & ALQ_NOACTIVATE) == 0)) { alq->aq_flags |= AQ_ACTIVE; activate = 1; } @@ -529,7 +540,7 @@ struct ale * alq_get(struct alq *alq, int flags) { /* should only be called in fixed length message (legacy) mode */ - KASSERT(alq->aq_entmax > 0 && alq->aq_entlen > 0, + KASSERT((alq->aq_entmax > 0 && alq->aq_entlen > 0), ("%s: fixed length get on variable length queue", __func__) ); return (alq_getn(alq, alq->aq_entlen, flags)); @@ -541,7 +552,7 @@ alq_getn(struct alq *alq, int len, int f struct ale *ale; int contigbytes; - KASSERT(len > 0 && len <= alq->aq_buflen, + KASSERT((len > 0 && len <= alq->aq_buflen), ("%s: len <= 0 || len > alq->aq_buflen", __func__) ); @@ -625,11 +636,12 @@ alq_getn(struct alq *alq, int len, int f } void -alq_post(struct alq *alq, struct ale *ale) +alq_post(struct alq *alq, struct ale *ale, int flags) { int activate; - if ((alq->aq_flags & AQ_ACTIVE) == 0) { + if (((alq->aq_flags & AQ_ACTIVE) == 0) && + ((flags & ALQ_NOACTIVATE) == 0)) { alq->aq_flags |= AQ_ACTIVE; activate = 1; } else Modified: user/lstewart/alq_varlen_8.x/sys/sys/alq.h ============================================================================== --- user/lstewart/alq_varlen_8.x/sys/sys/alq.h Thu Feb 12 13:04:13 2009 (r188512) +++ user/lstewart/alq_varlen_8.x/sys/sys/alq.h Thu Feb 12 13:49:51 2009 (r188513) @@ -52,6 +52,7 @@ struct ale { /* flags options */ #define ALQ_NOWAIT 0x0001 #define ALQ_WAITOK 0x0002 +#define ALQ_NOACTIVATE 0x0004 /* Suggested mode for file creation. */ #define ALQ_DEFAULT_CMODE 0600 @@ -124,6 +125,6 @@ struct ale *alq_getn(struct alq *alq, in * alq The queue to post the entry to. * ale An asynch logging entry returned by alq_get. */ -void alq_post(struct alq *alq, struct ale *ale); +void alq_post(struct alq *alq, struct ale *ale, int flags); #endif /* _SYS_ALQ_H_ */ Modified: user/lstewart/alq_varlen_8.x/tools/test/README ============================================================================== --- user/lstewart/alq_varlen_8.x/tools/test/README Thu Feb 12 13:04:13 2009 (r188512) +++ user/lstewart/alq_varlen_8.x/tools/test/README Thu Feb 12 13:49:51 2009 (r188513) @@ -11,3 +11,4 @@ devrandom Programs to test /dev/*random. dtrace DTrace test suite malloc A program to test and benchmark malloc(). posixshm A program to test POSIX shared memory. +alq A kernel module to put ALQ(9) through it's paces. Added: user/lstewart/alq_varlen_8.x/tools/test/alq/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/lstewart/alq_varlen_8.x/tools/test/alq/Makefile Thu Feb 12 13:49:51 2009 (r188513) @@ -0,0 +1,15 @@ +# $FreeBSD$ + +.include <bsd.own.mk> + +KMOD=alqtest +SRCS=alqtest.c alqtest.h +CLEANFILES=alqtest.h + +SYSDIR=/devel/freebsd_mirror/user/lstewart/alq_varlen_8.x/sys + +alqtest.h: + @awk -F "\n" '{ if(index($$0, "struct alq {") > 0) p=1; if(p == 1) { print $$0; if($$0 == "};") exit; } }' ${.CURDIR}/../../../sys/kern/kern_alq.c >> ${.TARGET} + +.include <bsd.kmod.mk> + Added: user/lstewart/alq_varlen_8.x/tools/test/alq/alqtest.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/lstewart/alq_varlen_8.x/tools/test/alq/alqtest.c Thu Feb 12 13:49:51 2009 (r188513) @@ -0,0 +1,425 @@ +/*- + * Copyright (c) 2008 Lawrence Stewart <lstewart@freebsd.org> + * 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 AUTHORS 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 AUTHORS 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. + */ + +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/unistd.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <sys/alq.h> +#include <sys/sbuf.h> +#include <machine/stdarg.h> + +#include "alqtest.h" + +MALLOC_DECLARE(M_ALQTEST); +MALLOC_DEFINE(M_ALQTEST, "alqtest", "dynamic memory used by alqtest"); + +#define ENABLE 0x01 +#define DISABLE 0x02 + +#define NUM_TEST_RUNS 1 + +static volatile uint8_t run_test_thread; + +static char logfile[PATH_MAX] = "/var/log/alqtest.log\0"; + +static struct thread *alq_test_thr = NULL; + +static struct mtx alqtestmtx; + +typedef int (*testfunc)(struct sbuf *, struct sbuf *); + +typedef const enum { + BLACK = 30, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE +} fgcolor_t; + +static int +sbuf_printf_color(struct sbuf *s, fgcolor_t c, const char *fmt, ...) +{ + va_list ap; + int ret; + + sbuf_printf(s, "\033[%dm", c); + va_start(ap, fmt); + ret = sbuf_vprintf(s, fmt, ap); + va_end(ap); + sbuf_printf(s, "\033[0m"); + + return (ret); +} + +static char +alqtest_randchar(void) +{ + uint32_t c; + + /* generate a random character in the ascii range [32, 126] */ + while ( (c = arc4random() % 126) < 32); + + return (char)c; +} + +static void +alqtest_doio_callback(void) +{ + printf("doing io baby!\n"); +} + +static int +alqtest_writen(struct sbuf *s, struct sbuf *debug) +{ + struct alq *testalq; + const int buflen = 100; + int i = 0, ret = 0, errors = 0; + char buf[buflen+1]; + + sbuf_printf(s, "- variable length message writing\n"); + + /* test variable length message writing */ + ret = alq_open( &testalq, + logfile, + curthread->td_ucred, + 0600, + buflen, + 0 + ); + + testalq->doio_debugcallback = &alqtest_doio_callback; + + for (i = 0; i < sizeof(buf); i++) + buf[i] = alqtest_randchar(); + + sbuf_printf(s, "-- msglen==1,buflen=%d\n", buflen); + alq_writen(testalq, buf, 1, ALQ_WAITOK | ALQ_NOACTIVATE); + + if ((buflen-1 != testalq->aq_freebytes) && + (1 != testalq->aq_writehead) && + (0 != testalq->aq_writetail)) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_freebytes", + buflen-1, + testalq->aq_freebytes + ); + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writehead", + 1, + testalq->aq_writehead + ); + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writetail", + 0, + testalq->aq_writetail + ); + } + + sbuf_printf(s, "-- msglen==%d,buflen=%d\n", buflen, buflen); + alq_writen(testalq, buf, buflen, ALQ_WAITOK); + + if ((0 != testalq->aq_freebytes) && + (0 != testalq->aq_writehead) && + (0 != testalq->aq_writetail)) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_freebytes", + 0, + testalq->aq_freebytes + ); + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writehead", + 0, + testalq->aq_writehead + ); + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writetail", + 0, + testalq->aq_writetail + ); + } + + alq_close(testalq); + + return errors; +} + +static int +alqtest_open(struct sbuf *s, struct sbuf *debug) +{ + struct alq *testalq; + const int buflen = 100; + int ret = 0, errors = 0; + + sbuf_printf(s, "- variable length message queue creation\n"); + + /* test variable length message queue creation */ + ret = alq_open( &testalq, + logfile, + curthread->td_ucred, + 0600, + buflen, + 0 + ); + + if (0 != testalq->aq_entmax) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_entmax", + 0, + testalq->aq_entmax + ); + } + + if (0 != testalq->aq_entlen) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_entlen", + 0, + testalq->aq_entlen + ); + } + + if (buflen != testalq->aq_freebytes) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_freebytes", + buflen, + testalq->aq_freebytes + ); + } + + if (buflen != testalq->aq_buflen) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_buflen", + buflen, + testalq->aq_buflen + ); + } + + if (0 != testalq->aq_writehead) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writehead", + 0, + testalq->aq_writehead + ); + } + + if (0 != testalq->aq_writetail) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_writetail", + 0, + testalq->aq_writetail + ); + } + + if (0 != testalq->aq_flags) { + errors++; + sbuf_printf( debug, + "alq->%-15s\texpected=%d\tactual=%d\n", + "aq_flags", + 0, + testalq->aq_flags + ); + } + + alq_close(testalq); + + return errors; +} + +static void +run_test(struct sbuf *s, const char *test_banner, testfunc test) +{ + struct sbuf *debug = NULL; + + if ((debug = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND)) != NULL) { + sbuf_printf(s, "########################################\n"); + sbuf_printf_color(s, GREEN, "%s\n", test_banner); + if (test(s, debug)) { + sbuf_finish(debug); + sbuf_printf_color(s, RED, "!!ERROR(S) FOUND!!\n"); + sbuf_printf(s, "%s", sbuf_data(debug)); + sbuf_printf_color(s, RED, "!!ERROR(S) FOUND!!\n"); + } + sbuf_printf(s, "########################################\n\n"); + sbuf_delete(debug); + } +} + +static void +alqtest_thread(void *arg) +{ + struct sbuf *s = NULL; + long runs = 0; + + /* loop until thread is signalled to exit */ + while (run_test_thread && runs < NUM_TEST_RUNS) { + if ((s = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND)) != NULL) { + sbuf_printf(s, "TEST RUN: %ld\n", ++runs); + + run_test(s, "alq_open", &alqtest_open); + run_test(s, "alq_writen", &alqtest_writen); + + sbuf_finish(s); + printf("%s", sbuf_data(s)); + sbuf_delete(s); + } + } + + kthread_exit(); +} + +static int +manage_test_ops(uint8_t action) +{ + int error = 0; + //struct sbuf *s = NULL; + + /* init an autosizing sbuf that initially holds 200 chars */ + //if ((s = sbuf_new(NULL, NULL, 200, SBUF_AUTOEXTEND)) == NULL) + // return -1; + + if (action == ENABLE) { + + run_test_thread = 1; + + kthread_add( &alqtest_thread, + NULL, + NULL, + &alq_test_thr, + RFNOWAIT, + 0, + "alq_test_thr" + ); + } + else if (action == DISABLE && alq_test_thr != NULL) { + /* tell the test thread that it should exit now */ + run_test_thread = 0; + alq_test_thr = NULL; + } + + return error; +} + +static int +deinit(void) +{ + manage_test_ops(DISABLE); + mtx_destroy(&alqtestmtx); + return 0; +} + +static int +init(void) +{ + mtx_init(&alqtestmtx, "alqtestmtx", NULL, MTX_DEF); + manage_test_ops(ENABLE); + return 0; +} + +/* + * This is the function that is called to load and unload the module. + * When the module is loaded, this function is called once with + * "what" == MOD_LOAD + * When the module is unloaded, this function is called twice with + * "what" = MOD_QUIESCE first, followed by "what" = MOD_UNLOAD second + * When the system is shut down e.g. CTRL-ALT-DEL or using the shutdown command, + * this function is called once with "what" = MOD_SHUTDOWN + * When the system is shut down, the handler isn't called until the very end + * of the shutdown sequence i.e. after the disks have been synced. + */ +static int alqtest_load_handler(module_t mod, int what, void *arg) +{ + switch(what) { + case MOD_LOAD: + return init(); + break; + + case MOD_QUIESCE: + case MOD_SHUTDOWN: + return deinit(); + break; + + case MOD_UNLOAD: + return 0; + break; + + default: + return EINVAL; + break; + } +} + +/* basic module data */ +static moduledata_t alqtest_mod = +{ + "alqtest", + alqtest_load_handler, /* execution entry point for the module */ + NULL +}; + +/* + * Param 1: name of the kernel module + * Param 2: moduledata_t struct containing info about the kernel module + * and the execution entry point for the module + * Param 3: From sysinit_sub_id enumeration in /usr/include/sys/kernel.h + * Defines the module initialisation order + * Param 4: From sysinit_elem_order enumeration in /usr/include/sys/kernel.h + * Defines the initialisation order of this kld relative to others + * within the same subsystem as defined by param 3 + */ +DECLARE_MODULE(alqtest, alqtest_mod, SI_SUB_SMP, SI_ORDER_ANY); +MODULE_DEPEND(alqtest, alq, 1, 1, 1); + +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902121349.n1CDnqrJ057249>