* Collect user-level profiling statistics; called on a profiling tick, * when a process is running in user-mode. This routine may be called * from an interrupt context. We perform the update with an AST * that will vector us to trap() with a context in which copyin and * copyout will work. Trap will then call addupc_task(). * * Note that we may (rarely) not get around to the AST soon enou
| 458 | * inaccurate. |
| 459 | */ |
| 460 | void |
| 461 | addupc_intr(struct thread *td, uintfptr_t pc, u_int ticks) |
| 462 | { |
| 463 | struct uprof *prof; |
| 464 | |
| 465 | if (ticks == 0) |
| 466 | return; |
| 467 | prof = &td->td_proc->p_stats->p_prof; |
| 468 | PROC_PROFLOCK(td->td_proc); |
| 469 | if (pc < prof->pr_off || PC_TO_INDEX(pc, prof) >= prof->pr_size) { |
| 470 | PROC_PROFUNLOCK(td->td_proc); |
| 471 | return; /* out of range; ignore */ |
| 472 | } |
| 473 | |
| 474 | PROC_PROFUNLOCK(td->td_proc); |
| 475 | td->td_profil_addr = pc; |
| 476 | td->td_profil_ticks = ticks; |
| 477 | td->td_pflags |= TDP_OWEUPC; |
| 478 | thread_lock(td); |
| 479 | td->td_flags |= TDF_ASTPENDING; |
| 480 | thread_unlock(td); |
| 481 | } |
| 482 | |
| 483 | /* |
| 484 | * Actually update the profiling statistics. If the update fails, we |