Module Name: src
Committed By: christos
Date: Thu Apr 30 00:48:10 UTC 2020
Modified Files:
src/sys/modules/examples: Makefile README
src/sys/modules/examples/ping: ping.c
Added Files:
src/sys/modules/examples/pollpal: Makefile cmd_pollpal.c pollpal.c
Log Message:
New kernel example module written by Ayushi Sharma
To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/modules/examples/Makefile
cvs rdiff -u -r1.14 -r1.15 src/sys/modules/examples/README
cvs rdiff -u -r1.3 -r1.4 src/sys/modules/examples/ping/ping.c
cvs rdiff -u -r0 -r1.1 src/sys/modules/examples/pollpal/Makefile \
src/sys/modules/examples/pollpal/cmd_pollpal.c \
src/sys/modules/examples/pollpal/pollpal.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/modules/examples/Makefile
diff -u src/sys/modules/examples/Makefile:1.10 src/sys/modules/examples/Makefile:1.11
--- src/sys/modules/examples/Makefile:1.10 Sat Apr 4 17:15:04 2020
+++ src/sys/modules/examples/Makefile Wed Apr 29 20:48:10 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.10 2020/04/04 21:15:04 kamil Exp $
+# $NetBSD: Makefile,v 1.11 2020/04/30 00:48:10 christos Exp $
.include <bsd.own.mk>
@@ -12,6 +12,7 @@ SUBDIR+= mapper # Needs an additional
SUBDIR+= panic_string # Crashes the system
SUBDIR+= ping # Needs an additional helper program
SUBDIR+= ping_block # Needs an additional helper program
+SUBDIR+= pollpal # Needs an additional helper program
SUBDIR+= properties
SUBDIR+= readhappy
SUBDIR+= readhappy_mpsafe # Contains an additional helper program
Index: src/sys/modules/examples/README
diff -u src/sys/modules/examples/README:1.14 src/sys/modules/examples/README:1.15
--- src/sys/modules/examples/README:1.14 Sat Apr 4 17:15:04 2020
+++ src/sys/modules/examples/README Wed Apr 29 20:48:10 2020
@@ -1,4 +1,4 @@
- $NetBSD: README,v 1.14 2020/04/04 21:15:04 kamil Exp $
+ $NetBSD: README,v 1.15 2020/04/30 00:48:10 christos Exp $
Kernel Developer's Manual
@@ -17,6 +17,7 @@ DESCRIPTION
* ping - basic ioctl(9)
* ping_block - basic ioctl(9) with a block device
* properties - handle incoming properties during the module load
+ * pollpal - implementation of basic poll(9) using palindrome
* readhappy - basic implementation of read(9) with happy numbers
* readhappy_mpsafe- demonstrates how to make a module MPSAFE
* sysctl - demonstrates adding a sysctl handle dynamically
@@ -82,5 +83,8 @@ HISTORY
The current_time module first appeared in NetBSD 10.0 and was authored by
Apurva Nandan.
+ The pollpall module first appeared in NetBSD 10.0 and was authored by
+ Ayushi Sharma.
+
AUTHORS
This document was written by Kamil Rytarowski.
Index: src/sys/modules/examples/ping/ping.c
diff -u src/sys/modules/examples/ping/ping.c:1.3 src/sys/modules/examples/ping/ping.c:1.4
--- src/sys/modules/examples/ping/ping.c:1.3 Wed Feb 5 09:10:46 2020
+++ src/sys/modules/examples/ping/ping.c Wed Apr 29 20:48:10 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ping.c,v 1.3 2020/02/05 14:10:46 pgoyette Exp $ */
+/* $NetBSD: ping.c,v 1.4 2020/04/30 00:48:10 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -27,13 +27,15 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ping.c,v 1.3 2020/02/05 14:10:46 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ping.c,v 1.4 2020/04/30 00:48:10 christos Exp $");
+#define DDB
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/systm.h>
#include "ping.h"
@@ -99,6 +101,7 @@ ping_ioctl(dev_t self __unused, u_long c
switch(cmd) {
case CMD_PING:
printf("ping: pong!\n");
+ Debugger();
return 0;
default:
return ENOTTY;
Added files:
Index: src/sys/modules/examples/pollpal/Makefile
diff -u /dev/null src/sys/modules/examples/pollpal/Makefile:1.1
--- /dev/null Wed Apr 29 20:48:10 2020
+++ src/sys/modules/examples/pollpal/Makefile Wed Apr 29 20:48:10 2020
@@ -0,0 +1,18 @@
+# $NetBSD: Makefile,v 1.1 2020/04/30 00:48:10 christos Exp $
+
+.include "../Makefile.inc"
+
+#S?= /usr/src/sys
+
+KMOD= pollpal
+SRCS= pollpal.c
+
+.include <bsd.kmodule.mk>
+
+# To make use of this module, you'll need to separately build the
+# cmd_pollpall program, with a Makefile similar to
+#
+# MKMAN= NO
+# PROG= cmd_pollpal
+# .include <bsd.prog.mk>
+
Index: src/sys/modules/examples/pollpal/cmd_pollpal.c
diff -u /dev/null src/sys/modules/examples/pollpal/cmd_pollpal.c:1.1
--- /dev/null Wed Apr 29 20:48:10 2020
+++ src/sys/modules/examples/pollpal/cmd_pollpal.c Wed Apr 29 20:48:10 2020
@@ -0,0 +1,130 @@
+/* $NetBSD: cmd_pollpal.c,v 1.1 2020/04/30 00:48:10 christos Exp $ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+__RCSID("$NetBSD: cmd_pollpal.c,v 1.1 2020/04/30 00:48:10 christos Exp $");
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <err.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BUFFLEN 100
+#define TIMEOUT 10000
+
+static int fd;
+
+static __dead __printflike(2, 3) void
+done(int e, const char *msg, ...)
+{
+ if (msg) {
+ va_list ap;
+
+ va_start(ap, msg);
+ verr(e, msg, ap);
+ /*NOTREACHED*/
+ va_end(ap);
+ }
+ exit(e);
+}
+
+static __dead void
+handler(int sig)
+{
+ done(EXIT_SUCCESS, NULL);
+}
+
+static const char dev[] = "/dev/pollpal";
+static const char wbuf[] = "abcdefghijklmnopqrstuvwxyz";
+
+int
+main(int argc, char **argv)
+{
+ struct pollfd fds;
+ ssize_t ret;
+ size_t i;
+ char rbuf[BUFFLEN];
+
+ setprogname(argv[0]);
+
+ fd = open(dev, O_RDWR, 0);
+ if (fd == -1)
+ err(EXIT_FAILURE, "open `%s'", dev);
+
+ fds.fd = fd;
+ fds.events = POLLOUT|POLLIN;
+
+ signal(SIGINT, handler);
+ for (i = 1; i <= 100; i++) {
+ ret = poll(&fds, 1, TIMEOUT);
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ done(EXIT_FAILURE, "poll");
+ }
+ printf("Poll_executing %zu times\n", i);
+ if (ret == 0) {
+ printf("%d seconds elapsed \n.TIMEOUT.\n",
+ TIMEOUT / 1000);
+ done(EXIT_SUCCESS, NULL);
+ }
+
+ if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
+ done(EXIT_FAILURE, "ERR|HUP|NVAL");
+
+ if (fds.revents & POLLOUT) {
+ do {
+ ret = write(fd, wbuf, sizeof(wbuf) - 1);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret == -1) {
+ done(EXIT_FAILURE, "write");
+ }
+ printf("Wrote %zd byte\n", ret);
+ }
+ if (fds.revents & POLLIN) {
+ memset(rbuf, 0, BUFFLEN);
+ do {
+ ret = read(fd, rbuf, BUFFLEN);
+ } while (ret == -1 && errno == EINTR);
+ if (ret == -1) {
+ done(EXIT_FAILURE, "read");
+ }
+ printf("Read %zd bytes\n", ret);
+ }
+ }
+ done(EXIT_SUCCESS, NULL);
+}
Index: src/sys/modules/examples/pollpal/pollpal.c
diff -u /dev/null src/sys/modules/examples/pollpal/pollpal.c:1.1
--- /dev/null Wed Apr 29 20:48:10 2020
+++ src/sys/modules/examples/pollpal/pollpal.c Wed Apr 29 20:48:10 2020
@@ -0,0 +1,317 @@
+/* $NetBSD: pollpal.c,v 1.1 2020/04/30 00:48:10 christos Exp $ */
+
+/*-
+* Copyright (c) 2020 The NetBSD Foundation, Inc.
+* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: pollpal.c,v 1.1 2020/04/30 00:48:10 christos Exp $");
+
+#include <sys/module.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/mutex.h>
+#include <sys/kmem.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+
+/*
+ * Create a device /dev/pollpal
+ *
+ * To use this device you need to do:
+ * mknod /dev/pollpal c 351 0
+ *
+ */
+
+dev_type_open(pollpal_open);
+
+static struct cdevsw pollpal_cdevsw = {
+ .d_open = pollpal_open,
+ .d_close = noclose,
+ .d_read = noread,
+ .d_write = nowrite,
+ .d_ioctl = noioctl,
+ .d_stop = nostop,
+ .d_tty = notty,
+ .d_poll = nopoll,
+ .d_mmap = nommap,
+ .d_kqfilter = nokqfilter,
+ .d_discard = nodiscard,
+ .d_flag = D_OTHER
+};
+
+static int pollpal_nopen = 0;
+
+static int pollpal_close(file_t *);
+static int pollpal_write(file_t *, off_t *, struct uio *, kauth_cred_t,
+ int);
+static int pollpal_read(file_t *, off_t *, struct uio *, kauth_cred_t,
+ int);
+static int pollpal_poll(file_t *, int);
+
+const struct fileops pollpal_fileops = {
+ .fo_read = pollpal_read,
+ .fo_write = pollpal_write,
+ .fo_ioctl = fbadop_ioctl,
+ .fo_fcntl = fnullop_fcntl,
+ .fo_poll = pollpal_poll,
+ .fo_stat = fbadop_stat,
+ .fo_close = pollpal_close,
+ .fo_kqfilter = fnullop_kqfilter,
+ .fo_restart = fnullop_restart,
+};
+
+typedef struct pollpal_softc {
+ kmutex_t lock;
+ kcondvar_t sc_cv;
+ struct selinfo psel;
+ char *buf;
+ size_t buf_len;
+ /* Device can have two states 1.READ_WAITING, 2.WRITE_WAITING. */
+ enum states {
+ READ_WAITING = 0,
+ WRITE_WAITING = 1
+ } sc_state;
+} pal_t;
+
+static int
+check_pal(const char *str, size_t len)
+{
+ size_t n;
+
+ n = 0;
+
+ while (n <= len / 2) {
+ if (str[n] != str[len - n - 1])
+ return 0;
+
+ n++;
+ }
+
+ return 1;
+}
+
+int
+pollpal_open(dev_t dev, int flag, int mode, struct lwp *l __unused)
+{
+ struct file *fp;
+ int error, fd;
+ pal_t *pl;
+
+ error = fd_allocfile(&fp, &fd);
+ if (error)
+ return error;
+
+ ++pollpal_nopen;
+
+ pl = kmem_zalloc(sizeof(*pl), KM_SLEEP);
+
+ pl->sc_state = READ_WAITING;
+ mutex_init(&pl->lock, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&pl->sc_cv, "sc_cv");
+ selinit(&pl->psel);
+
+ return fd_clone(fp, fd, flag, &pollpal_fileops, pl);
+}
+
+int
+pollpal_close(file_t * fp)
+{
+ pal_t * pl = fp->f_data;
+ KASSERT(pl != NULL);
+
+ if (pl->buf != NULL)
+ kmem_free(pl->buf, pl->buf_len);
+
+ seldestroy(&pl->psel);
+ cv_destroy(&pl->sc_cv);
+ mutex_destroy(&pl->lock);
+ kmem_free(pl, sizeof(*pl));
+
+ --pollpal_nopen;
+
+ return 0;
+}
+
+/*
+ * Device would write only in READ_WAITING state and then update the state to
+ * WRITE_WAITING.
+ */
+int
+pollpal_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
+ int flag)
+{
+ pal_t *pl = fp->f_data;
+ int error;
+
+ error = 0;
+
+ /* To ensure that only single process can write in device at a time. */
+ mutex_enter(&pl->lock);
+ cv_broadcast(&pl->sc_cv);
+ switch (pl->sc_state) {
+ case READ_WAITING:
+ pl->sc_state = WRITE_WAITING;
+ selnotify(&pl->psel, POLLOUT | POLLWRNORM, 0);
+ while (pl->sc_state == WRITE_WAITING) {
+ if (pl->buf) {
+ error = cv_wait_sig(&pl->sc_cv, &pl->lock);
+ if (error)
+ goto ret;
+
+ }
+
+ pl->buf_len = uio->uio_iov->iov_len;
+ pl->buf = kmem_alloc(pl->buf_len, KM_SLEEP);
+ uiomove(pl->buf, pl->buf_len, uio);
+ printf("Use cat to know the result.\n");
+ break;
+ }
+ break;
+ case WRITE_WAITING:
+ printf("State: WRITE_WAITING\n");
+ break;
+ }
+
+ret:
+ mutex_exit(&pl->lock);
+ return error;
+}
+
+/*
+ * Device would read only in WRITE_WAITING state and then update the state to
+ * READ_WAITING.
+ */
+int
+pollpal_read(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
+ int flags)
+{
+ pal_t *pl = fp->f_data;
+ int error;
+
+ error = 0;
+
+ /* To ensure that only single process can read device at a time. */
+ mutex_enter(&pl->lock);
+ cv_broadcast(&pl->sc_cv);
+ switch (pl->sc_state) {
+ case READ_WAITING:
+ printf("State: READ_WAITING\n");
+ printf("You need to write something to the module first!\n");
+ goto ret;
+ case WRITE_WAITING:
+ pl->sc_state = READ_WAITING;
+ selnotify(&pl->psel, POLLIN | POLLRDNORM, 0);
+ while (pl->sc_state == READ_WAITING) {
+ if (!pl->buf) {
+ error = cv_wait_sig(&pl->sc_cv, &pl->lock);
+ if (error)
+ goto ret;
+
+ }
+ printf("The string you entered was: ");
+ uiomove(pl->buf, pl->buf_len, uio);
+ printf("\n");
+ if (check_pal(pl->buf, pl->buf_len))
+ printf("String '%s' was a palindrome.\n",
+ pl->buf);
+ else
+ printf("String '%s' was not a palindrome.\n",
+ pl->buf);
+
+ break;
+ }
+ break;
+ }
+ kmem_free(pl->buf, pl->buf_len);
+ pl->buf = NULL;
+
+ret:
+ mutex_exit(&pl->lock);
+ return error;
+}
+
+int
+pollpal_poll(struct file *fp, int events)
+{
+ pal_t *pl = fp->f_data;
+ int revents;
+
+ revents = 0;
+
+ mutex_enter(&pl->lock);
+ switch (pl->sc_state) {
+ case READ_WAITING:
+ if (events & (POLLOUT | POLLWRNORM)) {
+ /* When device is in READ_WAITING state it can write */
+ revents |= POLLOUT | POLLWRNORM;
+ } else {
+ /* Record the request if it wasn't satisfied. */
+ selrecord(curlwp, &pl->psel);
+ }
+ break;
+ case WRITE_WAITING:
+ if (events && (POLLIN | POLLRDNORM)) {
+ /* When device is in WRITE_WAITING state it can read. */
+ revents |= POLLIN;
+ } else {
+ /* Record the request if it wasn't satisfied. */
+ selrecord(curlwp, &pl->psel);
+ }
+ break;
+ }
+
+ mutex_exit(&pl->lock);
+ return revents;
+}
+
+MODULE(MODULE_CLASS_MISC, pollpal, NULL);
+
+static int
+pollpal_modcmd(modcmd_t cmd, void *arg __unused)
+{
+ int cmajor = 351, bmajor = -1;
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+ if (devsw_attach("pollpal", NULL, &bmajor, &pollpal_cdevsw,
+ &cmajor))
+ return ENXIO;
+ return 0;
+ case MODULE_CMD_FINI:
+ if (pollpal_nopen != 0)
+ return EBUSY;
+ return devsw_detach(NULL, &pollpal_cdevsw);
+ default:
+ return ENOTTY;
+ }
+}