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;
+	} 
+}

Reply via email to