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 --- |