Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/sys Introduce a generic linear hook list



details:   https://anonhg.NetBSD.org/src/rev/6f3509584d68
branches:  trunk
changeset: 1023864:6f3509584d68
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Thu Sep 30 01:26:07 2021 +0000

description:
Introduce a generic linear hook list

diffstat:

 distrib/sets/lists/comp/mi |    3 +-
 sys/kern/kern_hook.c       |  207 ++++++++++++++++++++++++++++++++++++++++++++-
 sys/sys/Makefile           |    4 +-
 sys/sys/hook.h             |   52 +++++++++++
 4 files changed, 261 insertions(+), 5 deletions(-)

diffs (truncated from 329 to 300 lines):

diff -r 6571f1fbdf48 -r 6f3509584d68 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi        Thu Sep 30 01:20:53 2021 +0000
+++ b/distrib/sets/lists/comp/mi        Thu Sep 30 01:26:07 2021 +0000
@@ -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
diff -r 6571f1fbdf48 -r 6f3509584d68 sys/kern/kern_hook.c
--- a/sys/kern/kern_hook.c      Thu Sep 30 01:20:53 2021 +0000
+++ b/sys/kern/kern_hook.c      Thu Sep 30 01:26:07 2021 +0000
@@ -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 @@
 };
 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 @@
        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;
+}
diff -r 6571f1fbdf48 -r 6f3509584d68 sys/sys/Makefile
--- a/sys/sys/Makefile  Thu Sep 30 01:20:53 2021 +0000
+++ b/sys/sys/Makefile  Thu Sep 30 01:26:07 2021 +0000
@@ -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 @@
        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 \
diff -r 6571f1fbdf48 -r 6f3509584d68 sys/sys/hook.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/sys/hook.h    Thu Sep 30 01:26:07 2021 +0000
@@ -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



Home | Main Index | Thread Index | Old Index