Author: markj
Date: Sat Aug 24 21:13:38 2013
New Revision: 254813
URL: http://svnweb.freebsd.org/changeset/base/254813

Log:
  Rename the kld_unload event handler to kld_unload_try, and add a new
  kld_unload event handler which gets invoked after a linker file has been
  successfully unloaded. The kld_unload and kld_load event handlers are now
  invoked with the shared linker lock held, while kld_unload_try is invoked
  with the lock exclusively held.
  
  Convert hwpmc(4) to use these event handlers instead of having
  kern_kldload() and kern_kldunload() invoke hwpmc(4) hooks whenever files are
  loaded or unloaded. This has no functional effect, but simplifes the linker
  code somewhat.
  
  Reviewed by:  jhb

Modified:
  head/share/man/man9/EVENTHANDLER.9
  head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
  head/sys/cddl/dev/dtrace/dtrace_load.c
  head/sys/cddl/dev/dtrace/dtrace_unload.c
  head/sys/cddl/dev/sdt/sdt.c
  head/sys/dev/hwpmc/hwpmc_mod.c
  head/sys/kern/kern_linker.c
  head/sys/sys/eventhandler.h
  head/sys/sys/pmckern.h

Modified: head/share/man/man9/EVENTHANDLER.9
==============================================================================
--- head/share/man/man9/EVENTHANDLER.9  Sat Aug 24 21:09:57 2013        
(r254812)
+++ head/share/man/man9/EVENTHANDLER.9  Sat Aug 24 21:13:38 2013        
(r254813)
@@ -202,6 +202,8 @@ Callbacks invoked when a BPF listener at
 .It Vt kld_load
 Callbacks invoked after a linker file has been loaded.
 .It Vt kld_unload
+Callbacks invoked after a linker file has been successfully unloaded.
+.It Vt kld_unload_try
 Callbacks invoked before a linker file is about to be unloaded.
 These callbacks may be used to return an error and prevent the unload from
 proceeding.

Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Sat Aug 
24 21:09:57 2013        (r254812)
+++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Sat Aug 
24 21:13:38 2013        (r254813)
@@ -242,7 +242,7 @@ int         dtrace_in_probe;        /* non-zero if exe
 uintptr_t      dtrace_in_probe_addr;   /* Address of invop when already in 
probe */
 #endif
 static eventhandler_tag        dtrace_kld_load_tag;
-static eventhandler_tag        dtrace_kld_unload_tag;
+static eventhandler_tag        dtrace_kld_unload_try_tag;
 #endif
 
 /*
@@ -15351,7 +15351,7 @@ dtrace_kld_load(void *arg __unused, link
 }
 
 static void
-dtrace_kld_unload(void *arg __unused, linker_file_t lf, int *error)
+dtrace_kld_unload_try(void *arg __unused, linker_file_t lf, int *error)
 {
 
        if (*error != 0)

Modified: head/sys/cddl/dev/dtrace/dtrace_load.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_load.c      Sat Aug 24 21:09:57 2013        
(r254812)
+++ head/sys/cddl/dev/dtrace/dtrace_load.c      Sat Aug 24 21:13:38 2013        
(r254813)
@@ -59,8 +59,8 @@ dtrace_load(void *dummy)
        /* Register callbacks for linker file load and unload events. */
        dtrace_kld_load_tag = EVENTHANDLER_REGISTER(kld_load,
            dtrace_kld_load, NULL, EVENTHANDLER_PRI_ANY);
-       dtrace_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload,
-           dtrace_kld_unload, NULL, EVENTHANDLER_PRI_ANY);
+       dtrace_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try,
+           dtrace_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY);
 
        /*
         * Initialise the mutexes without 'witness' because the dtrace

Modified: head/sys/cddl/dev/dtrace/dtrace_unload.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_unload.c    Sat Aug 24 21:09:57 2013        
(r254812)
+++ head/sys/cddl/dev/dtrace/dtrace_unload.c    Sat Aug 24 21:13:38 2013        
(r254813)
@@ -68,7 +68,7 @@ dtrace_unload()
 
        dtrace_provider = NULL;
        EVENTHANDLER_DEREGISTER(kld_load, dtrace_kld_load_tag);
-       EVENTHANDLER_DEREGISTER(kld_unload, dtrace_kld_unload_tag);
+       EVENTHANDLER_DEREGISTER(kld_unload_try, dtrace_kld_unload_try_tag);
 
        if ((state = dtrace_anon_grab()) != NULL) {
                /*

Modified: head/sys/cddl/dev/sdt/sdt.c
==============================================================================
--- head/sys/cddl/dev/sdt/sdt.c Sat Aug 24 21:09:57 2013        (r254812)
+++ head/sys/cddl/dev/sdt/sdt.c Sat Aug 24 21:13:38 2013        (r254813)
@@ -59,7 +59,7 @@ static int    sdt_unload(void *);
 static void    sdt_create_provider(struct sdt_provider *);
 static void    sdt_create_probe(struct sdt_probe *);
 static void    sdt_kld_load(void *, struct linker_file *);
-static void    sdt_kld_unload(void *, struct linker_file *, int *);
+static void    sdt_kld_unload_try(void *, struct linker_file *, int *);
 
 static MALLOC_DEFINE(M_SDT, "SDT", "DTrace SDT providers");
 
@@ -95,7 +95,7 @@ static struct cdev    *sdt_cdev;
 static TAILQ_HEAD(, sdt_provider) sdt_prov_list;
 
 eventhandler_tag       sdt_kld_load_tag;
-eventhandler_tag       sdt_kld_unload_tag;
+eventhandler_tag       sdt_kld_unload_try_tag;
 
 static void
 sdt_create_provider(struct sdt_provider *prov)
@@ -264,7 +264,7 @@ sdt_kld_load(void *arg __unused, struct 
 }
 
 static void
-sdt_kld_unload(void *arg __unused, struct linker_file *lf, int *error __unused)
+sdt_kld_unload_try(void *arg __unused, struct linker_file *lf, int *error 
__unused)
 {
        struct sdt_provider *prov, **curr, **begin, **end, *tmp;
 
@@ -319,8 +319,8 @@ sdt_load(void *arg __unused)
 
        sdt_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, sdt_kld_load, NULL,
            EVENTHANDLER_PRI_ANY);
-       sdt_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload, sdt_kld_unload,
-           NULL, EVENTHANDLER_PRI_ANY);
+       sdt_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try,
+           sdt_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY);
 
        /* Pick up probes from the kernel and already-loaded linker files. */
        linker_file_foreach(sdt_linker_file_cb, NULL);
@@ -332,7 +332,7 @@ sdt_unload(void *arg __unused)
        struct sdt_provider *prov, *tmp;
 
        EVENTHANDLER_DEREGISTER(kld_load, sdt_kld_load_tag);
-       EVENTHANDLER_DEREGISTER(kld_unload, sdt_kld_unload_tag);
+       EVENTHANDLER_DEREGISTER(kld_unload_try, sdt_kld_unload_try_tag);
 
        sdt_probe_func = sdt_probe_stub;
 

Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c      Sat Aug 24 21:09:57 2013        
(r254812)
+++ head/sys/dev/hwpmc/hwpmc_mod.c      Sat Aug 24 21:13:38 2013        
(r254813)
@@ -132,7 +132,8 @@ static int          *pmc_pmcdisp;    /* PMC row di
 
 
 /* various event handlers */
-static eventhandler_tag        pmc_exit_tag, pmc_fork_tag;
+static eventhandler_tag        pmc_exit_tag, pmc_fork_tag, pmc_kld_load_tag,
+    pmc_kld_unload_tag;
 
 /* Module statistics */
 struct pmc_op_getdriverstats pmc_stats;
@@ -1476,50 +1477,6 @@ pmc_process_csw_out(struct thread *td)
 }
 
 /*
- * Log a KLD operation.
- */
-
-static void
-pmc_process_kld_load(struct pmckern_map_in *pkm)
-{
-       struct pmc_owner *po;
-
-       sx_assert(&pmc_sx, SX_LOCKED);
-
-       /*
-        * Notify owners of system sampling PMCs about KLD operations.
-        */
-
-       LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
-           if (po->po_flags & PMC_PO_OWNS_LOGFILE)
-               pmclog_process_map_in(po, (pid_t) -1, pkm->pm_address,
-                   (char *) pkm->pm_file);
-
-       /*
-        * TODO: Notify owners of (all) process-sampling PMCs too.
-        */
-
-       return;
-}
-
-static void
-pmc_process_kld_unload(struct pmckern_map_out *pkm)
-{
-       struct pmc_owner *po;
-
-       sx_assert(&pmc_sx, SX_LOCKED);
-
-       LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
-           if (po->po_flags & PMC_PO_OWNS_LOGFILE)
-               pmclog_process_map_out(po, (pid_t) -1,
-                   pkm->pm_address, pkm->pm_address + pkm->pm_size);
-
-       /*
-        * TODO: Notify owners of process-sampling PMCs.
-        */
-}
-
-/*
  * A mapping change for a process.
  */
 
@@ -1833,8 +1790,8 @@ const char *pmc_hooknames[] = {
        "CSW-IN",
        "CSW-OUT",
        "SAMPLE",
-       "KLDLOAD",
-       "KLDUNLOAD",
+       "UNUSED1",
+       "UNUSED2",
        "MMAP",
        "MUNMAP",
        "CALLCHAIN-NMI",
@@ -2002,17 +1959,6 @@ pmc_hook_handler(struct thread *td, int 
                pmc_process_samples(PCPU_GET(cpuid), PMC_SR);
                break;
 
-
-       case PMC_FN_KLD_LOAD:
-               sx_assert(&pmc_sx, SX_LOCKED);
-               pmc_process_kld_load((struct pmckern_map_in *) arg);
-               break;
-
-       case PMC_FN_KLD_UNLOAD:
-               sx_assert(&pmc_sx, SX_LOCKED);
-               pmc_process_kld_unload((struct pmckern_map_out *) arg);
-               break;
-
        case PMC_FN_MMAP:
                sx_assert(&pmc_sx, SX_LOCKED);
                pmc_process_mmap(td, (struct pmckern_map_in *) arg);
@@ -4644,6 +4590,47 @@ pmc_process_fork(void *arg __unused, str
        sx_xunlock(&pmc_sx);
 }
 
+static void
+pmc_kld_load(void *arg __unused, linker_file_t lf)
+{
+       struct pmc_owner *po;
+
+       sx_slock(&pmc_sx);
+
+       /*
+        * Notify owners of system sampling PMCs about KLD operations.
+        */
+       LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+               if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+                       pmclog_process_map_in(po, (pid_t) -1,
+                           (uintfptr_t) lf->address, lf->filename);
+
+       /*
+        * TODO: Notify owners of (all) process-sampling PMCs too.
+        */
+
+       sx_sunlock(&pmc_sx);
+}
+
+static void
+pmc_kld_unload(void *arg __unused, const char *filename __unused,
+    caddr_t address, size_t size)
+{
+       struct pmc_owner *po;
+
+       sx_slock(&pmc_sx);
+
+       LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+               if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+                       pmclog_process_map_out(po, (pid_t) -1,
+                           (uintfptr_t) address, (uintfptr_t) address + size);
+
+       /*
+        * TODO: Notify owners of process-sampling PMCs.
+        */
+
+       sx_sunlock(&pmc_sx);
+}
 
 /*
  * initialization
@@ -4913,6 +4900,12 @@ pmc_initialize(void)
        pmc_fork_tag = EVENTHANDLER_REGISTER(process_fork,
            pmc_process_fork, NULL, EVENTHANDLER_PRI_ANY);
 
+       /* register kld event handlers */
+       pmc_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, pmc_kld_load,
+           NULL, EVENTHANDLER_PRI_ANY);
+       pmc_kld_unload_tag = EVENTHANDLER_REGISTER(kld_unload, pmc_kld_unload,
+           NULL, EVENTHANDLER_PRI_ANY);
+
        /* initialize logging */
        pmclog_initialize();
 
@@ -4970,6 +4963,8 @@ pmc_cleanup(void)
        /* deregister event handlers */
        EVENTHANDLER_DEREGISTER(process_fork, pmc_fork_tag);
        EVENTHANDLER_DEREGISTER(process_exit, pmc_exit_tag);
+       EVENTHANDLER_DEREGISTER(kld_load, pmc_kld_load_tag);
+       EVENTHANDLER_DEREGISTER(kld_unload, pmc_kld_unload_tag);
 
        /* send SIGBUS to all owner threads, free up allocations */
        if (pmc_ownerhash)

Modified: head/sys/kern/kern_linker.c
==============================================================================
--- head/sys/kern/kern_linker.c Sat Aug 24 21:09:57 2013        (r254812)
+++ head/sys/kern/kern_linker.c Sat Aug 24 21:13:38 2013        (r254813)
@@ -995,9 +995,6 @@ linker_search_symbol_name(caddr_t value,
 int
 kern_kldload(struct thread *td, const char *file, int *fileid)
 {
-#ifdef HWPMC_HOOKS
-       struct pmckern_map_in pkm;
-#endif
        const char *kldname, *modname;
        linker_file_t lf;
        int error;
@@ -1037,17 +1034,9 @@ kern_kldload(struct thread *td, const ch
        if (fileid != NULL)
                *fileid = lf->id;
 
-       EVENTHANDLER_INVOKE(kld_load, lf);
-
-#ifdef HWPMC_HOOKS
        sx_downgrade(&kld_sx);
-       pkm.pm_file = lf->filename;
-       pkm.pm_address = (uintptr_t) lf->address;
-       PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
+       EVENTHANDLER_INVOKE(kld_load, lf);
        sx_sunlock(&kld_sx);
-#else
-       sx_xunlock(&kld_sx);
-#endif
 
 done:
        CURVNET_RESTORE();
@@ -1076,10 +1065,10 @@ sys_kldload(struct thread *td, struct kl
 int
 kern_kldunload(struct thread *td, int fileid, int flags)
 {
-#ifdef HWPMC_HOOKS
-       struct pmckern_map_out pkm;
-#endif
        linker_file_t lf;
+       char *filename = NULL;
+       caddr_t address;
+       size_t size;
        int error = 0;
 
        if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
@@ -1094,7 +1083,7 @@ kern_kldunload(struct thread *td, int fi
        if (lf) {
                KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
 
-               EVENTHANDLER_INVOKE(kld_unload, lf, &error);
+               EVENTHANDLER_INVOKE(kld_unload_try, lf, &error);
                if (error != 0)
                        error = EBUSY;
                else if (lf->userrefs == 0) {
@@ -1105,11 +1094,11 @@ kern_kldunload(struct thread *td, int fi
                            " loaded by the kernel\n");
                        error = EBUSY;
                } else {
-#ifdef HWPMC_HOOKS
-                       /* Save data needed by hwpmc(4) before unloading. */
-                       pkm.pm_address = (uintptr_t) lf->address;
-                       pkm.pm_size = lf->size;
-#endif
+                       /* Save data needed for the kld_unload callbacks. */
+                       filename = strdup(lf->filename, M_TEMP);
+                       address = lf->address;
+                       size = lf->size;
+
                        lf->userrefs--;
                        error = linker_file_unload(lf, flags);
                        if (error)
@@ -1118,16 +1107,14 @@ kern_kldunload(struct thread *td, int fi
        } else
                error = ENOENT;
 
-#ifdef HWPMC_HOOKS
        if (error == 0) {
                sx_downgrade(&kld_sx);
-               PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
+               EVENTHANDLER_INVOKE(kld_unload, filename, address, size);
                sx_sunlock(&kld_sx);
        } else
                sx_xunlock(&kld_sx);
-#else
-       sx_xunlock(&kld_sx);
-#endif
+       free(filename, M_TEMP);
+
        CURVNET_RESTORE();
        return (error);
 }

Modified: head/sys/sys/eventhandler.h
==============================================================================
--- head/sys/sys/eventhandler.h Sat Aug 24 21:09:57 2013        (r254812)
+++ head/sys/sys/eventhandler.h Sat Aug 24 21:13:38 2013        (r254813)
@@ -269,8 +269,10 @@ EVENTHANDLER_DECLARE(maxsockets_change, 
 /* Kernel linker file load and unload events */
 struct linker_file;
 typedef void (*kld_load_fn)(void *, struct linker_file *);
-typedef void (*kld_unload_fn)(void *, struct linker_file *, int *);
+typedef void (*kld_unload_fn)(void *, const char *, caddr_t, size_t);
+typedef void (*kld_unload_try_fn)(void *, struct linker_file *, int *);
 EVENTHANDLER_DECLARE(kld_load, kld_load_fn);
 EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn);
+EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn);
 
 #endif /* SYS_EVENTHANDLER_H */

Modified: head/sys/sys/pmckern.h
==============================================================================
--- head/sys/sys/pmckern.h      Sat Aug 24 21:09:57 2013        (r254812)
+++ head/sys/sys/pmckern.h      Sat Aug 24 21:13:38 2013        (r254813)
@@ -51,8 +51,8 @@
 #define        PMC_FN_CSW_IN                   2
 #define        PMC_FN_CSW_OUT                  3
 #define        PMC_FN_DO_SAMPLES               4
-#define        PMC_FN_KLD_LOAD                 5
-#define        PMC_FN_KLD_UNLOAD               6
+#define        PMC_FN_UNUSED1                  5
+#define        PMC_FN_UNUSED2                  6
 #define        PMC_FN_MMAP                     7
 #define        PMC_FN_MUNMAP                   8
 #define        PMC_FN_USER_CALLCHAIN           9
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to