Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c
Show First 20 Lines • Show All 961 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
int | int | ||||
fasttrap_pid_probe(struct trapframe *tf) | fasttrap_pid_probe(struct trapframe *tf) | ||||
{ | { | ||||
struct reg reg, *rp; | struct reg reg, *rp; | ||||
proc_t *p = curproc, *pp; | proc_t *p = curproc, *pp; | ||||
struct rm_priotracker tracker; | struct rm_priotracker tracker; | ||||
uint64_t gen; | |||||
uintptr_t pc; | uintptr_t pc; | ||||
uintptr_t new_pc = 0; | uintptr_t new_pc = 0; | ||||
fasttrap_bucket_t *bucket; | fasttrap_bucket_t *bucket; | ||||
#ifdef illumos | #ifdef illumos | ||||
kmutex_t *pid_mtx; | kmutex_t *pid_mtx; | ||||
#endif | #endif | ||||
fasttrap_tracepoint_t *tp, tp_local; | fasttrap_tracepoint_t *tp, tp_local; | ||||
pid_t pid; | pid_t pid; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | #ifdef illumos | ||||
pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; | pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; | ||||
mutex_enter(pid_mtx); | mutex_enter(pid_mtx); | ||||
#else | #else | ||||
pp = p; | pp = p; | ||||
sx_slock(&proctree_lock); | sx_slock(&proctree_lock); | ||||
while (pp->p_vmspace == pp->p_pptr->p_vmspace) | while (pp->p_vmspace == pp->p_pptr->p_vmspace) | ||||
pp = pp->p_pptr; | pp = pp->p_pptr; | ||||
pid = pp->p_pid; | pid = pp->p_pid; | ||||
if (pp != p) { | |||||
PROC_LOCK(pp); | |||||
if ((pp->p_flag & P_WEXIT) != 0) { | |||||
/* | |||||
* This can happen if the child was created with | |||||
* rfork(2). Userspace tracing cannot work reliably in | |||||
* such a scenario, but we can at least try. | |||||
*/ | |||||
PROC_UNLOCK(pp); | |||||
sx_sunlock(&proctree_lock); | sx_sunlock(&proctree_lock); | ||||
pp = NULL; | return (-1); | ||||
} | |||||
_PHOLD_LITE(pp); | |||||
PROC_UNLOCK(pp); | |||||
} | |||||
sx_sunlock(&proctree_lock); | |||||
rm_rlock(&fasttrap_tp_lock, &tracker); | rm_rlock(&fasttrap_tp_lock, &tracker); | ||||
#endif | #endif | ||||
bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; | bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; | ||||
/* | /* | ||||
* Lookup the tracepoint that the process just hit. | * Lookup the tracepoint that the process just hit. | ||||
*/ | */ | ||||
for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { | for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { | ||||
if (pid == tp->ftt_pid && pc == tp->ftt_pc && | if (pid == tp->ftt_pid && pc == tp->ftt_pc && | ||||
tp->ftt_proc->ftpc_acount != 0) | tp->ftt_proc->ftpc_acount != 0) | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* If we couldn't find a matching tracepoint, either a tracepoint has | * If we couldn't find a matching tracepoint, either a tracepoint has | ||||
* been inserted without using the pid<pid> ioctl interface (see | * been inserted without using the pid<pid> ioctl interface (see | ||||
* fasttrap_ioctl), or somehow we have mislaid this tracepoint. | * fasttrap_ioctl), or somehow we have mislaid this tracepoint. | ||||
*/ | */ | ||||
if (tp == NULL) { | if (tp == NULL) { | ||||
#ifdef illumos | #ifdef illumos | ||||
mutex_exit(pid_mtx); | mutex_exit(pid_mtx); | ||||
return (-1); | |||||
#else | #else | ||||
rm_runlock(&fasttrap_tp_lock, &tracker); | rm_runlock(&fasttrap_tp_lock, &tracker); | ||||
#endif | gen = atomic_load_acq_64(&pp->p_fasttrap_tp_gen); | ||||
if (pp != p) | |||||
PRELE(pp); | |||||
if (curthread->t_fasttrap_tp_gen != gen) { | |||||
/* | |||||
* At least one tracepoint associated with this PID has | |||||
* been removed from the table since #BP was raised. | |||||
* Speculate that we hit a tracepoint that has since | |||||
* been removed, and retry the instruction. | |||||
*/ | |||||
curthread->t_fasttrap_tp_gen = gen; | |||||
tf->tf_rip = pc; | |||||
return (0); | |||||
} | |||||
return (-1); | return (-1); | ||||
#endif | |||||
} | } | ||||
if (pp != p) | |||||
PRELE(pp); | |||||
/* | /* | ||||
* Set the program counter to the address of the traced instruction | * Set the program counter to the address of the traced instruction | ||||
* so that it looks right in ustack() output. | * so that it looks right in ustack() output. | ||||
*/ | */ | ||||
rp->r_rip = pc; | rp->r_rip = pc; | ||||
if (tp->ftt_ids != NULL) { | if (tp->ftt_ids != NULL) { | ||||
▲ Show 20 Lines • Show All 830 Lines • Show Last 20 Lines |