Deleted Added
full compact
hwpmc_mod.c (147191) hwpmc_mod.c (147708)
1/*-
2 * Copyright (c) 2003-2005 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003-2005 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 147191 2005-06-09 19:45:09Z jkoshy $");
29__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 147708 2005-06-30 19:01:26Z jkoshy $");
30
31#include <sys/param.h>
32#include <sys/eventhandler.h>
33#include <sys/jail.h>
34#include <sys/kernel.h>
35#include <sys/kthread.h>
36#include <sys/limits.h>
37#include <sys/lock.h>

--- 618 unchanged lines hidden (view full) ---

656}
657
658/*
659 * Get the file name for an executable. This is a simple wrapper
660 * around vn_fullpath(9).
661 */
662
663static void
30
31#include <sys/param.h>
32#include <sys/eventhandler.h>
33#include <sys/jail.h>
34#include <sys/kernel.h>
35#include <sys/kthread.h>
36#include <sys/limits.h>
37#include <sys/lock.h>

--- 618 unchanged lines hidden (view full) ---

656}
657
658/*
659 * Get the file name for an executable. This is a simple wrapper
660 * around vn_fullpath(9).
661 */
662
663static void
664pmc_getprocname(struct proc *p, char **fullpath, char **freepath)
664pmc_getfilename(struct vnode *v, char **fullpath, char **freepath)
665{
666 struct thread *td;
667
668 td = curthread;
669 *fullpath = "unknown";
670 *freepath = NULL;
665{
666 struct thread *td;
667
668 td = curthread;
669 *fullpath = "unknown";
670 *freepath = NULL;
671 vn_lock(p->p_textvp, LK_EXCLUSIVE | LK_RETRY, td);
672 vn_fullpath(td, p->p_textvp, fullpath, freepath);
673 VOP_UNLOCK(p->p_textvp, 0, td);
671 vn_lock(v, LK_EXCLUSIVE | LK_RETRY, td);
672 vn_fullpath(td, v, fullpath, freepath);
673 VOP_UNLOCK(v, 0, td);
674}
675
676/*
677 * remove an process owning PMCs
678 */
679
680void
681pmc_remove_owner(struct pmc_owner *po)

--- 264 unchanged lines hidden (view full) ---

946 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)) &&
947 (pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) == 0)
948 pm->pm_flags |= PMC_F_NEEDS_LOGFILE;
949
950 pm->pm_flags |= PMC_F_ATTACH_DONE; /* mark as attached */
951
952 /* issue an attach event to a configured log file */
953 if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) {
674}
675
676/*
677 * remove an process owning PMCs
678 */
679
680void
681pmc_remove_owner(struct pmc_owner *po)

--- 264 unchanged lines hidden (view full) ---

946 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)) &&
947 (pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) == 0)
948 pm->pm_flags |= PMC_F_NEEDS_LOGFILE;
949
950 pm->pm_flags |= PMC_F_ATTACH_DONE; /* mark as attached */
951
952 /* issue an attach event to a configured log file */
953 if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) {
954 pmc_getprocname(p, &fullpath, &freepath);
954 pmc_getfilename(p->p_textvp, &fullpath, &freepath);
955 pmclog_process_pmcattach(pm, p->p_pid, fullpath);
956 if (freepath)
957 FREE(freepath, M_TEMP);
958 }
959 /* mark process as using HWPMCs */
960 PROC_LOCK(p);
961 p->p_flag |= P_HWPMC;
962 PROC_UNLOCK(p);

--- 474 unchanged lines hidden (view full) ---

1437 {
1438
1439 /*
1440 * Process exec()
1441 */
1442
1443 case PMC_FN_PROCESS_EXEC:
1444 {
955 pmclog_process_pmcattach(pm, p->p_pid, fullpath);
956 if (freepath)
957 FREE(freepath, M_TEMP);
958 }
959 /* mark process as using HWPMCs */
960 PROC_LOCK(p);
961 p->p_flag |= P_HWPMC;
962 PROC_UNLOCK(p);

--- 474 unchanged lines hidden (view full) ---

1437 {
1438
1439 /*
1440 * Process exec()
1441 */
1442
1443 case PMC_FN_PROCESS_EXEC:
1444 {
1445 int *credentials_changed;
1446 char *fullpath, *freepath;
1447 unsigned int ri;
1448 int is_using_hwpmcs;
1449 struct pmc *pm;
1450 struct proc *p;
1451 struct pmc_owner *po;
1452 struct pmc_process *pp;
1445 char *fullpath, *freepath;
1446 unsigned int ri;
1447 int is_using_hwpmcs;
1448 struct pmc *pm;
1449 struct proc *p;
1450 struct pmc_owner *po;
1451 struct pmc_process *pp;
1452 struct pmckern_procexec *pk;
1453
1454 sx_assert(&pmc_sx, SX_XLOCKED);
1455
1456 p = td->td_proc;
1453
1454 sx_assert(&pmc_sx, SX_XLOCKED);
1455
1456 p = td->td_proc;
1457 pmc_getprocname(p, &fullpath, &freepath);
1457 pmc_getfilename(p->p_textvp, &fullpath, &freepath);
1458
1458
1459 pk = (struct pmckern_procexec *) arg;
1460
1459 /* Inform owners of SS mode PMCs of the exec event. */
1460 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1461 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1461 /* Inform owners of SS mode PMCs of the exec event. */
1462 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1463 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1462 pmclog_process_procexec(po, p->p_pid, fullpath);
1464 pmclog_process_procexec(po, PMC_ID_INVALID,
1465 p->p_pid, pk->pm_entryaddr, fullpath);
1463
1464 PROC_LOCK(p);
1465 is_using_hwpmcs = p->p_flag & P_HWPMC;
1466 PROC_UNLOCK(p);
1467
1468 if (!is_using_hwpmcs) {
1469 if (freepath)
1470 FREE(freepath, M_TEMP);

--- 23 unchanged lines hidden (view full) ---

1494 * owners who have already recieved the event because
1495 * the have system sampling PMCs active.
1496 */
1497 for (ri = 0; ri < md->pmd_npmc; ri++)
1498 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) {
1499 po = pm->pm_owner;
1500 if (po->po_sscount == 0 &&
1501 po->po_flags & PMC_PO_OWNS_LOGFILE)
1466
1467 PROC_LOCK(p);
1468 is_using_hwpmcs = p->p_flag & P_HWPMC;
1469 PROC_UNLOCK(p);
1470
1471 if (!is_using_hwpmcs) {
1472 if (freepath)
1473 FREE(freepath, M_TEMP);

--- 23 unchanged lines hidden (view full) ---

1497 * owners who have already recieved the event because
1498 * the have system sampling PMCs active.
1499 */
1500 for (ri = 0; ri < md->pmd_npmc; ri++)
1501 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) {
1502 po = pm->pm_owner;
1503 if (po->po_sscount == 0 &&
1504 po->po_flags & PMC_PO_OWNS_LOGFILE)
1502 pmclog_process_procexec(po, p->p_pid,
1505 pmclog_process_procexec(po, pm->pm_id,
1506 p->p_pid, pk->pm_entryaddr,
1503 fullpath);
1504 }
1505
1506 if (freepath)
1507 FREE(freepath, M_TEMP);
1508
1507 fullpath);
1508 }
1509
1510 if (freepath)
1511 FREE(freepath, M_TEMP);
1512
1509 credentials_changed = arg;
1510
1511 PMCDBG(PRC,EXC,1, "exec proc=%p (%d, %s) cred-changed=%d",
1513
1514 PMCDBG(PRC,EXC,1, "exec proc=%p (%d, %s) cred-changed=%d",
1512 p, p->p_pid, p->p_comm, *credentials_changed);
1515 p, p->p_pid, p->p_comm, pk->pm_credentialschanged);
1513
1516
1514 if (*credentials_changed == 0) /* credentials didn't change */
1517 if (pk->pm_credentialschanged == 0) /* no change */
1515 break;
1516
1517 /*
1518 * If the newly exec()'ed process has a different credential
1519 * than before, allow it to be the target of a PMC only if
1520 * the PMC's owner has sufficient priviledge.
1521 */
1522

--- 1929 unchanged lines hidden (view full) ---

3452 * added, a bit is set in mask 'pmc_cpumask' denoting that the
3453 * DO_SAMPLES hook needs to be invoked from the clock handler.
3454 *
3455 * This function is meant to be called from an NMI handler. It cannot
3456 * use any of the locking primitives supplied by the OS.
3457 */
3458
3459int
1518 break;
1519
1520 /*
1521 * If the newly exec()'ed process has a different credential
1522 * than before, allow it to be the target of a PMC only if
1523 * the PMC's owner has sufficient priviledge.
1524 */
1525

--- 1929 unchanged lines hidden (view full) ---

3455 * added, a bit is set in mask 'pmc_cpumask' denoting that the
3456 * DO_SAMPLES hook needs to be invoked from the clock handler.
3457 *
3458 * This function is meant to be called from an NMI handler. It cannot
3459 * use any of the locking primitives supplied by the OS.
3460 */
3461
3462int
3460pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode)
3463pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode)
3461{
3462 int error, ri;
3463 struct thread *td;
3464 struct pmc_sample *ps;
3465 struct pmc_samplebuffer *psb;
3466
3467 error = 0;
3468 ri = PMC_TO_ROWINDEX(pm);
3469
3470 psb = pmc_pcpu[cpu]->pc_sb;
3471
3472 ps = psb->ps_write;
3473 if (ps->ps_pc) { /* in use, reader hasn't caught up */
3474 atomic_add_int(&pmc_stats.pm_intr_bufferfull, 1);
3475 atomic_set_int(&pm->pm_flags, PMC_F_IS_STALLED);
3476 PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d",
3464{
3465 int error, ri;
3466 struct thread *td;
3467 struct pmc_sample *ps;
3468 struct pmc_samplebuffer *psb;
3469
3470 error = 0;
3471 ri = PMC_TO_ROWINDEX(pm);
3472
3473 psb = pmc_pcpu[cpu]->pc_sb;
3474
3475 ps = psb->ps_write;
3476 if (ps->ps_pc) { /* in use, reader hasn't caught up */
3477 atomic_add_int(&pmc_stats.pm_intr_bufferfull, 1);
3478 atomic_set_int(&pm->pm_flags, PMC_F_IS_STALLED);
3479 PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d",
3477 cpu, pm, (int64_t) pc, usermode,
3480 cpu, pm, (uint64_t) pc, usermode,
3478 (int) (psb->ps_write - psb->ps_samples),
3479 (int) (psb->ps_read - psb->ps_samples));
3480 error = ENOMEM;
3481 goto done;
3482 }
3483
3484 /* fill in entry */
3485 PMCDBG(SAM,INT,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, pm,
3481 (int) (psb->ps_write - psb->ps_samples),
3482 (int) (psb->ps_read - psb->ps_samples));
3483 error = ENOMEM;
3484 goto done;
3485 }
3486
3487 /* fill in entry */
3488 PMCDBG(SAM,INT,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, pm,
3486 (int64_t) pc, usermode,
3489 (uint64_t) pc, usermode,
3487 (int) (psb->ps_write - psb->ps_samples),
3488 (int) (psb->ps_read - psb->ps_samples));
3489
3490 atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
3491 ps->ps_pmc = pm;
3492 if ((td = curthread) && td->td_proc)
3493 ps->ps_pid = td->td_proc->p_pid;
3494 else

--- 49 unchanged lines hidden (view full) ---

3544 ("[pmc,%d] pmc=%p non-sampling mode=%d", __LINE__,
3545 pm, PMC_TO_MODE(pm)));
3546
3547 /* Ignore PMCs that have been switched off */
3548 if (pm->pm_state != PMC_STATE_RUNNING)
3549 goto entrydone;
3550
3551 PMCDBG(SAM,OPS,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu,
3490 (int) (psb->ps_write - psb->ps_samples),
3491 (int) (psb->ps_read - psb->ps_samples));
3492
3493 atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
3494 ps->ps_pmc = pm;
3495 if ((td = curthread) && td->td_proc)
3496 ps->ps_pid = td->td_proc->p_pid;
3497 else

--- 49 unchanged lines hidden (view full) ---

3547 ("[pmc,%d] pmc=%p non-sampling mode=%d", __LINE__,
3548 pm, PMC_TO_MODE(pm)));
3549
3550 /* Ignore PMCs that have been switched off */
3551 if (pm->pm_state != PMC_STATE_RUNNING)
3552 goto entrydone;
3553
3554 PMCDBG(SAM,OPS,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu,
3552 pm, (int64_t) ps->ps_pc, ps->ps_usermode,
3555 pm, (uint64_t) ps->ps_pc, ps->ps_usermode,
3553 (int) (psb->ps_write - psb->ps_samples),
3554 (int) (psb->ps_read - psb->ps_samples));
3555
3556 /*
3557 * If this is a process-mode PMC that is attached to
3558 * its owner, and if the PC is in user mode, update
3559 * profiling statistics like timer-based profiling
3560 * would have done.

--- 202 unchanged lines hidden (view full) ---

3763 * Unlink this process from the PMCs that are
3764 * targetting it. This will send a signal to
3765 * all PMC owner's whose PMCs are orphaned.
3766 *
3767 * Log PMC value at exit time if requested.
3768 */
3769 for (ri = 0; ri < md->pmd_npmc; ri++)
3770 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) {
3556 (int) (psb->ps_write - psb->ps_samples),
3557 (int) (psb->ps_read - psb->ps_samples));
3558
3559 /*
3560 * If this is a process-mode PMC that is attached to
3561 * its owner, and if the PC is in user mode, update
3562 * profiling statistics like timer-based profiling
3563 * would have done.

--- 202 unchanged lines hidden (view full) ---

3766 * Unlink this process from the PMCs that are
3767 * targetting it. This will send a signal to
3768 * all PMC owner's whose PMCs are orphaned.
3769 *
3770 * Log PMC value at exit time if requested.
3771 */
3772 for (ri = 0; ri < md->pmd_npmc; ri++)
3773 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) {
3771 if (pm->pm_flags & PMC_F_LOG_PROCEXIT)
3774 if (pm->pm_flags & PMC_F_NEEDS_LOGFILE)
3772 pmclog_process_procexit(pm, pp);
3773 pmc_unlink_target_process(pm, pp);
3774 }
3775 FREE(pp, M_PMC);
3776
3777 } else
3778 critical_exit(); /* pp == NULL */
3779

--- 407 unchanged lines hidden ---
3775 pmclog_process_procexit(pm, pp);
3776 pmc_unlink_target_process(pm, pp);
3777 }
3778 FREE(pp, M_PMC);
3779
3780 } else
3781 critical_exit(); /* pp == NULL */
3782

--- 407 unchanged lines hidden ---