Module Name:    src
Committed By:   yamaguchi
Date:           Thu Sep 30 01:26:08 UTC 2021

Modified Files:
        src/distrib/sets/lists/comp: mi
        src/sys/kern: kern_hook.c
        src/sys/sys: Makefile
Added Files:
        src/sys/sys: hook.h

Log Message:
Introduce a generic linear hook list


To generate a diff of this commit:
cvs rdiff -u -r1.2393 -r1.2394 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.8 -r1.9 src/sys/kern/kern_hook.c
cvs rdiff -u -r1.178 -r1.179 src/sys/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/sys/hook.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2393 src/distrib/sets/lists/comp/mi:1.2394
--- src/distrib/sets/lists/comp/mi:1.2393	Sun Sep 19 15:51:27 2021
+++ src/distrib/sets/lists/comp/mi	Thu Sep 30 01:26:07 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2393 2021/09/19 15:51:27 thorpej Exp $
+#	$NetBSD: mi,v 1.2394 2021/09/30 01:26:07 yamaguchi Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -3306,6 +3306,7 @@
 ./usr/include/sys/gmon.h			comp-c-include
 ./usr/include/sys/gpio.h			comp-c-include
 ./usr/include/sys/hash.h			comp-c-include
+./usr/include/sys/hook.h			comp-c-include
 ./usr/include/sys/idtype.h			comp-c-include
 ./usr/include/sys/ieee754.h			comp-c-include
 ./usr/include/sys/intr.h			comp-c-include

Index: src/sys/kern/kern_hook.c
diff -u src/sys/kern/kern_hook.c:1.8 src/sys/kern/kern_hook.c:1.9
--- src/sys/kern/kern_hook.c:1.8	Wed Oct 16 18:29:49 2019
+++ src/sys/kern/kern_hook.c	Thu Sep 30 01:26:07 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_hook.c,v 1.8 2019/10/16 18:29:49 christos Exp $	*/
+/*	$NetBSD: kern_hook.c,v 1.9 2021/09/30 01:26:07 yamaguchi Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -31,13 +31,16 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.8 2019/10/16 18:29:49 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.9 2021/09/30 01:26:07 yamaguchi Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
 #include <sys/rwlock.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/hook.h>
+#include <sys/kmem.h>
+#include <sys/condvar.h>
 
 /*
  * A generic linear hook.
@@ -49,6 +52,23 @@ struct hook_desc {
 };
 typedef LIST_HEAD(, hook_desc) hook_list_t;
 
+enum hook_list_st {
+	HKLIST_IDLE,
+	HKLIST_INUSE,
+};
+
+struct khook_list {
+	hook_list_t	 hl_list;
+	kmutex_t	 hl_lock;
+	kmutex_t	*hl_cvlock;
+	struct lwp	*hl_lwp;
+	kcondvar_t	 hl_cv;
+	enum hook_list_st
+			 hl_state;
+	khook_t		*hl_active_hk;
+	char		 hl_namebuf[HOOKNAMSIZ];
+};
+
 int	powerhook_debug = 0;
 
 static void *
@@ -398,3 +418,186 @@ dopowerhooks(int why)
 	if (powerhook_debug)
 		printf("dopowerhooks: %s done\n", why_name);
 }
+
+/*
+ * A simple linear hook.
+ */
+
+khook_list_t *
+simplehook_create(int ipl, const char *wmsg)
+{
+	khook_list_t *l;
+
+	l = kmem_zalloc(sizeof(*l), KM_SLEEP);
+
+	mutex_init(&l->hl_lock, MUTEX_DEFAULT, ipl);
+	strlcpy(l->hl_namebuf, wmsg, sizeof(l->hl_namebuf));
+	cv_init(&l->hl_cv, l->hl_namebuf);
+	LIST_INIT(&l->hl_list);
+	l->hl_state = HKLIST_IDLE;
+
+	return l;
+}
+
+void
+simplehook_destroy(khook_list_t *l)
+{
+	struct hook_desc *hd;
+
+	KASSERT(l->hl_state == HKLIST_IDLE);
+
+	while ((hd = LIST_FIRST(&l->hl_list)) != NULL) {
+		LIST_REMOVE(hd, hk_list);
+		kmem_free(hd, sizeof(*hd));
+	}
+
+	cv_destroy(&l->hl_cv);
+	mutex_destroy(&l->hl_lock);
+	kmem_free(l, sizeof(*l));
+}
+
+int
+simplehook_dohooks(khook_list_t *l)
+{
+	struct hook_desc *hd, *nexthd;
+	kmutex_t *cv_lock;
+	void (*fn)(void *);
+	void *arg;
+
+	mutex_enter(&l->hl_lock);
+	if (l->hl_state != HKLIST_IDLE) {
+		mutex_exit(&l->hl_lock);
+		return EBUSY;
+	}
+
+	/* stop removing hooks */
+	l->hl_state = HKLIST_INUSE;
+	l->hl_lwp = curlwp;
+
+	LIST_FOREACH(hd, &l->hl_list, hk_list) {
+		if (hd->hk_fn == NULL)
+			continue;
+
+		fn = hd->hk_fn;
+		arg = hd->hk_arg;
+		l->hl_active_hk = hd;
+		l->hl_cvlock = NULL;
+
+		mutex_exit(&l->hl_lock);
+
+		/* do callback without l->hl_lock */
+		(*fn)(arg);
+
+		mutex_enter(&l->hl_lock);
+		l->hl_active_hk = NULL;
+		cv_lock = l->hl_cvlock;
+
+		if (hd->hk_fn == NULL) {
+			if (cv_lock != NULL) {
+				mutex_exit(&l->hl_lock);
+				mutex_enter(cv_lock);
+			}
+
+			cv_broadcast(&l->hl_cv);
+
+			if (cv_lock != NULL) {
+				mutex_exit(cv_lock);
+				mutex_enter(&l->hl_lock);
+			}
+		}
+	}
+
+	/* remove marked node while running hooks */
+	LIST_FOREACH_SAFE(hd, &l->hl_list, hk_list, nexthd) {
+		if (hd->hk_fn == NULL) {
+			LIST_REMOVE(hd, hk_list);
+			kmem_free(hd, sizeof(*hd));
+		}
+	}
+
+	l->hl_lwp = NULL;
+	l->hl_state = HKLIST_IDLE;
+	mutex_exit(&l->hl_lock);
+
+	return 0;
+}
+
+khook_t *
+simplehook_establish(khook_list_t *l,  void (*fn)(void *), void *arg)
+{
+	struct hook_desc *hd;
+
+	hd = kmem_zalloc(sizeof(*hd), KM_SLEEP);
+	hd->hk_fn = fn;
+	hd->hk_arg = arg;
+
+	mutex_enter(&l->hl_lock);
+	LIST_INSERT_HEAD(&l->hl_list, hd, hk_list);
+	mutex_exit(&l->hl_lock);
+
+	return hd;
+}
+
+void
+simplehook_disestablish(khook_list_t *l, khook_t *hd, kmutex_t *lock)
+{
+	struct hook_desc *hd0 __diagused;
+	kmutex_t *cv_lock;
+
+	KASSERT(lock == NULL || mutex_owned(lock));
+	mutex_enter(&l->hl_lock);
+
+#ifdef DIAGNOSTIC
+	LIST_FOREACH(hd0, &l->hl_list, hk_list) {
+		if (hd == hd0)
+			break;
+	}
+
+	if (hd0 == NULL)
+		panic("hook_disestablish: hook %p not established", hd);
+#endif
+
+	/* The hook is not referred, remove immidiately */
+	if (l->hl_state == HKLIST_IDLE) {
+		LIST_REMOVE(hd, hk_list);
+		kmem_free(hd, sizeof(*hd));
+		mutex_exit(&l->hl_lock);
+		return;
+	}
+
+	/* remove callback. hd will be removed in dohooks */
+	hd->hk_fn = NULL;
+	hd->hk_arg = NULL;
+
+	/* If the hook is running, wait for the completion */
+	if (l->hl_active_hk == hd &&
+	    l->hl_lwp != curlwp) {
+		if (lock != NULL) {
+			cv_lock = lock;
+			KASSERT(l->hl_cvlock == NULL);
+			l->hl_cvlock = lock;
+			mutex_exit(&l->hl_lock);
+		} else {
+			cv_lock = &l->hl_lock;
+		}
+
+		cv_wait(&l->hl_cv, cv_lock);
+
+		if (lock == NULL)
+			mutex_exit(&l->hl_lock);
+	} else {
+		mutex_exit(&l->hl_lock);
+	}
+}
+
+bool
+simplehook_has_hooks(khook_list_t *l)
+{
+	bool empty;
+
+	mutex_enter(&l->hl_lock);
+	empty = LIST_EMPTY(&l->hl_list);
+	mutex_exit(&l->hl_lock);
+
+	return !empty;
+}

Index: src/sys/sys/Makefile
diff -u src/sys/sys/Makefile:1.178 src/sys/sys/Makefile:1.179
--- src/sys/sys/Makefile:1.178	Sun Sep 19 15:51:27 2021
+++ src/sys/sys/Makefile	Thu Sep 30 01:26:07 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.178 2021/09/19 15:51:27 thorpej Exp $
+#	$NetBSD: Makefile,v 1.179 2021/09/30 01:26:07 yamaguchi Exp $
 
 .include <bsd.own.mk>
 
@@ -23,7 +23,7 @@ INCS=	acct.h acl.h agpio.h aio.h ansi.h 
 	fault.h \
 	fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
 	flashio.h float_ieee754.h fstypes.h futex.h gcq.h gmon.h gpio.h hash.h \
-	idtype.h ieee754.h intr.h intrio.h inttypes.h ioccom.h ioctl.h \
+	hook.h idtype.h ieee754.h intr.h intrio.h inttypes.h ioccom.h ioctl.h \
 	ioctl_compat.h iostat.h ipc.h ipmi.h \
 	joystick.h \
 	kcore.h kcov.h kcpuset.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \

Added files:

Index: src/sys/sys/hook.h
diff -u /dev/null src/sys/sys/hook.h:1.1
--- /dev/null	Thu Sep 30 01:26:08 2021
+++ src/sys/sys/hook.h	Thu Sep 30 01:26:07 2021
@@ -0,0 +1,52 @@
+/*	$NetBSD: hook.h,v 1.1 2021/09/30 01:26:07 yamaguchi Exp $	*/
+
+/*
+ * Copyright (c) 2021 Internet Initiative Japan 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.
+ */
+
+#ifndef _SYS_HOOK_H_
+#define _SYS_HOOK_H_
+
+#include <sys/mutex.h>
+
+#define HOOKNAMSIZ	128
+
+struct khook_list;
+struct hook_desc;
+
+typedef struct khook_list	khook_list_t;
+typedef struct hook_desc	khook_t;
+
+khook_list_t	*simplehook_create(int, const char *);
+void		 simplehook_destroy(khook_list_t *);
+int		 simplehook_dohooks(khook_list_t *);
+
+khook_t		*simplehook_establish(khook_list_t *,
+		    void (*)(void *), void *);
+void		 simplehook_disestablish(khook_list_t *,
+		    khook_t *, kmutex_t *);
+bool		 simplehook_has_hooks(khook_list_t *);
+
+#endif /* !_SYS_HOOK_H_ */

Reply via email to