svn commit: r188513 - in user/lstewart/alq_varlen_8.x: sys/kern
sys/sys tools/test tools/test/alq
Lawrence Stewart
lstewart at FreeBSD.org
Thu Feb 12 05:49:52 PST 2009
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 at 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);
+
+
More information about the svn-src-user
mailing list