Page MenuHomeFreeBSD

D12882.id34570.diff
No OneTemporary

D12882.id34570.diff

Index: sys/dev/hwpmc/hwpmc_logging.c
===================================================================
--- sys/dev/hwpmc/hwpmc_logging.c
+++ sys/dev/hwpmc/hwpmc_logging.c
@@ -49,6 +49,7 @@
#include <sys/pmclog.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/uio.h>
@@ -234,6 +235,54 @@
return (plb ? 0 : ENOMEM);
}
+struct pmclog_proc_init_args {
+ struct proc *kthr;
+ struct pmc_owner *po;
+ bool exit;
+ bool acted;
+};
+
+int
+pmclog_proc_create(struct thread *td, void **handlep)
+{
+ struct pmclog_proc_init_args *ia;
+ int error;
+
+ ia = malloc(sizeof(*ia), M_TEMP, M_WAITOK | M_ZERO);
+ error = kproc_create(pmclog_loop, ia, &ia->kthr,
+ RFHIGHPID, 0, "hwpmc: proc(%d)", td->td_proc->p_pid);
+ if (error == 0)
+ *handlep = ia;
+ return (error);
+}
+
+void
+pmclog_proc_ignite(void *handle, struct pmc_owner *po)
+{
+ struct pmclog_proc_init_args *ia;
+
+ ia = handle;
+ mtx_lock(&pmc_kthread_mtx);
+ MPASS(!ia->acted);
+ MPASS(ia->po == NULL);
+ MPASS(!ia->exit);
+ MPASS(ia->kthr != NULL);
+ if (po == NULL) {
+ ia->exit = true;
+ } else {
+ ia->po = po;
+ KASSERT(po->po_kthread == NULL,
+ ("[pmclog,%d] po=%p kthread (%p) already present",
+ __LINE__, po, po->po_kthread));
+ po->po_kthread = ia->kthr;
+ }
+ wakeup(ia);
+ while (!ia->acted)
+ msleep(ia, &pmc_kthread_mtx, PWAIT, "pmclogw", 0);
+ mtx_unlock(&pmc_kthread_mtx);
+ free(ia, M_TEMP);
+}
+
/*
* Log handler loop.
*
@@ -243,20 +292,45 @@
static void
pmclog_loop(void *arg)
{
- int error;
+ struct pmclog_proc_init_args *ia;
struct pmc_owner *po;
struct pmclog_buffer *lb;
struct proc *p;
struct ucred *ownercred;
struct ucred *mycred;
struct thread *td;
+ sigset_t unb;
struct uio auio;
struct iovec aiov;
size_t nbytes;
+ int error;
- po = (struct pmc_owner *) arg;
- p = po->po_owner;
td = curthread;
+
+ SIGEMPTYSET(unb);
+ SIGADDSET(unb, SIGHUP);
+ (void)kern_sigprocmask(td, SIG_UNBLOCK, &unb, NULL, 0);
+
+ ia = arg;
+ MPASS(ia->kthr == curproc);
+ MPASS(!ia->acted);
+ mtx_lock(&pmc_kthread_mtx);
+ while (ia->po == NULL && !ia->exit)
+ msleep(ia, &pmc_kthread_mtx, PWAIT, "pmclogi", 0);
+ if (ia->exit) {
+ ia->acted = true;
+ wakeup(ia);
+ mtx_unlock(&pmc_kthread_mtx);
+ kproc_exit(0);
+ }
+ MPASS(ia->po != NULL);
+ po = ia->po;
+ ia->acted = true;
+ wakeup(ia);
+ mtx_unlock(&pmc_kthread_mtx);
+ ia = NULL;
+
+ p = po->po_owner;
mycred = td->td_ucred;
PROC_LOCK(p);
@@ -291,16 +365,8 @@
mtx_unlock_spin(&po->po_mtx);
/* No more buffers and shutdown required. */
- if (po->po_flags & PMC_PO_SHUTDOWN) {
- mtx_unlock(&pmc_kthread_mtx);
- /*
- * Close the file to get PMCLOG_EOF
- * error in pmclog(3).
- */
- fo_close(po->po_file, curthread);
- mtx_lock(&pmc_kthread_mtx);
+ if (po->po_flags & PMC_PO_SHUTDOWN)
break;
- }
(void) msleep(po, &pmc_kthread_mtx, PWAIT,
"pmcloop", 0);
@@ -541,19 +607,16 @@
static void
pmclog_stop_kthread(struct pmc_owner *po)
{
- /*
- * Close the file to force the thread out of fo_write,
- * unset flag, wakeup the helper thread,
- * wait for it to exit
- */
-
- if (po->po_file != NULL)
- fo_close(po->po_file, curthread);
mtx_lock(&pmc_kthread_mtx);
po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
+ if (po->po_kthread != NULL) {
+ PROC_LOCK(po->po_kthread);
+ kern_psignal(po->po_kthread, SIGHUP);
+ PROC_UNLOCK(po->po_kthread);
+ }
wakeup_one(po);
- if (po->po_kthread)
+ while (po->po_kthread != NULL)
msleep(po->po_kthread, &pmc_kthread_mtx, PPAUSE, "pmckstp", 0);
mtx_unlock(&pmc_kthread_mtx);
}
@@ -572,15 +635,11 @@
int
pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
{
- int error;
struct proc *p;
cap_rights_t rights;
- /*
- * As long as it is possible to get a LOR between pmc_sx lock and
- * proctree/allproc sx locks used for adding a new process, assure
- * the former is not held here.
- */
- sx_assert(&pmc_sx, SA_UNLOCKED);
+ int error;
+
+ sx_assert(&pmc_sx, SA_XLOCKED);
PMCDBG2(LOG,CFG,1, "config po=%p logfd=%d", po, logfd);
p = po->po_owner;
@@ -589,9 +648,6 @@
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
return (EBUSY);
- KASSERT(po->po_kthread == NULL,
- ("[pmclog,%d] po=%p kthread (%p) already present", __LINE__, po,
- po->po_kthread));
KASSERT(po->po_file == NULL,
("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
po->po_file));
@@ -604,10 +660,6 @@
/* mark process as owning a log file */
po->po_flags |= PMC_PO_OWNS_LOGFILE;
- error = kproc_create(pmclog_loop, po, &po->po_kthread,
- RFHIGHPID, 0, "hwpmc: proc(%d)", p->p_pid);
- if (error)
- goto error;
/* mark process as using HWPMCs */
PROC_LOCK(p);
@@ -624,10 +676,6 @@
return (0);
error:
- /* shutdown the thread */
- if (po->po_kthread)
- pmclog_stop_kthread(po);
-
KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
"stopped", __LINE__, po));
@@ -685,8 +733,11 @@
}
/* drop a reference to the fd */
- error = fdrop(po->po_file, curthread);
- po->po_file = NULL;
+ if (po->po_file != NULL) {
+ error = fdrop(po->po_file, curthread);
+ po->po_file = NULL;
+ } else
+ error = 0;
po->po_error = 0;
return (error);
Index: sys/dev/hwpmc/hwpmc_mod.c
===================================================================
--- sys/dev/hwpmc/hwpmc_mod.c
+++ sys/dev/hwpmc/hwpmc_mod.c
@@ -311,27 +311,23 @@
/* The `sysent' for the new syscall */
static struct sysent pmc_sysent = {
- 2, /* sy_narg */
- pmc_syscall_handler /* sy_call */
+ .sy_narg = 2,
+ .sy_call = pmc_syscall_handler,
};
static struct syscall_module_data pmc_syscall_mod = {
- load,
- NULL,
- &pmc_syscall_num,
- &pmc_sysent,
-#if (__FreeBSD_version >= 1100000)
- { 0, NULL },
- SY_THR_STATIC_KLD,
-#else
- { 0, NULL }
-#endif
+ .chainevh = load,
+ .chainarg = NULL,
+ .offset = &pmc_syscall_num,
+ .new_sysent = &pmc_sysent,
+ .old_sysent = { .sy_narg = 0, .sy_call = NULL },
+ .flags = SY_THR_STATIC_KLD,
};
static moduledata_t pmc_mod = {
- PMC_MODULE_NAME,
- syscall_module_handler,
- &pmc_syscall_mod
+ .name = PMC_MODULE_NAME,
+ .evhand = syscall_module_handler,
+ .priv = &pmc_syscall_mod,
};
#ifdef EARLY_AP_STARTUP
@@ -2858,21 +2854,30 @@
static int
pmc_syscall_handler(struct thread *td, void *syscall_args)
{
- int error, is_sx_downgraded, is_sx_locked, op;
+ int error, is_sx_downgraded, op;
struct pmc_syscall_args *c;
+ void *pmclog_proc_handle;
void *arg;
- PMC_GET_SX_XLOCK(ENOSYS);
-
- DROP_GIANT();
-
- is_sx_downgraded = 0;
- is_sx_locked = 1;
-
- c = (struct pmc_syscall_args *) syscall_args;
-
+ c = (struct pmc_syscall_args *)syscall_args;
op = c->pmop_code;
arg = c->pmop_data;
+ if (op == PMC_OP_CONFIGURELOG) {
+ /*
+ * We cannot create the logging process inside
+ * pmclog_configure_log() because there is a LOR
+ * between pmc_sx and process structure locks.
+ * Instead, pre-create the process and ignite the loop
+ * if everything is fine, otherwise direct the process
+ * to exit.
+ */
+ error = pmclog_proc_create(td, &pmclog_proc_handle);
+ if (error != 0)
+ goto done_syscall;
+ }
+
+ PMC_GET_SX_XLOCK(ENOSYS);
+ is_sx_downgraded = 0;
PMCDBG3(MOD,PMS,1, "syscall op=%d \"%s\" arg=%p", op,
pmc_op_to_name[op], arg);
@@ -2880,8 +2885,7 @@
error = 0;
atomic_add_int(&pmc_stats.pm_syscalls, 1);
- switch(op)
- {
+ switch (op) {
/*
@@ -2897,15 +2901,16 @@
struct pmc_owner *po;
struct pmc_op_configurelog cl;
- sx_assert(&pmc_sx, SX_XLOCKED);
-
- if ((error = copyin(arg, &cl, sizeof(cl))) != 0)
+ if ((error = copyin(arg, &cl, sizeof(cl))) != 0) {
+ pmclog_proc_ignite(pmclog_proc_handle, NULL);
break;
+ }
/* mark this process as owning a log file */
p = td->td_proc;
if ((po = pmc_find_owner_descriptor(p)) == NULL)
if ((po = pmc_allocate_owner_descriptor(p)) == NULL) {
+ pmclog_proc_ignite(pmclog_proc_handle, NULL);
error = ENOMEM;
break;
}
@@ -2917,10 +2922,11 @@
* de-configure it.
*/
if (cl.pm_logfd >= 0) {
- sx_xunlock(&pmc_sx);
- is_sx_locked = 0;
error = pmclog_configure_log(md, po, cl.pm_logfd);
+ pmclog_proc_ignite(pmclog_proc_handle, error == 0 ?
+ po : NULL);
} else if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
+ pmclog_proc_ignite(pmclog_proc_handle, NULL);
pmclog_process_closelog(po);
error = pmclog_close(po);
if (error == 0) {
@@ -2930,11 +2936,10 @@
pmc_stop(pm);
error = pmclog_deconfigure_log(po);
}
- } else
+ } else {
+ pmclog_proc_ignite(pmclog_proc_handle, NULL);
error = EINVAL;
-
- if (error)
- break;
+ }
}
break;
@@ -4029,19 +4034,15 @@
break;
}
- if (is_sx_locked != 0) {
- if (is_sx_downgraded)
- sx_sunlock(&pmc_sx);
- else
- sx_xunlock(&pmc_sx);
- }
-
+ if (is_sx_downgraded)
+ sx_sunlock(&pmc_sx);
+ else
+ sx_xunlock(&pmc_sx);
+done_syscall:
if (error)
atomic_add_int(&pmc_stats.pm_syscall_errors, 1);
- PICKUP_GIANT();
-
- return error;
+ return (error);
}
/*
Index: sys/sys/pmclog.h
===================================================================
--- sys/sys/pmclog.h
+++ sys/sys/pmclog.h
@@ -260,6 +260,8 @@
int pmclog_flush(struct pmc_owner *_po);
int pmclog_close(struct pmc_owner *_po);
void pmclog_initialize(void);
+int pmclog_proc_create(struct thread *td, void **handlep);
+void pmclog_proc_ignite(void *handle, struct pmc_owner *po);
void pmclog_process_callchain(struct pmc *_pm, struct pmc_sample *_ps);
void pmclog_process_closelog(struct pmc_owner *po);
void pmclog_process_dropnotify(struct pmc_owner *po);

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 9, 9:19 AM (4 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15731213
Default Alt Text
D12882.id34570.diff (9 KB)

Event Timeline