* Actually update the profiling statistics. If the update fails, we * simply turn off profiling. */
| 485 | * simply turn off profiling. |
| 486 | */ |
| 487 | void |
| 488 | addupc_task(struct thread *td, uintfptr_t pc, u_int ticks) |
| 489 | { |
| 490 | struct proc *p = td->td_proc; |
| 491 | struct uprof *prof; |
| 492 | caddr_t addr; |
| 493 | u_int i; |
| 494 | u_short v; |
| 495 | int stop = 0; |
| 496 | |
| 497 | if (ticks == 0) |
| 498 | return; |
| 499 | |
| 500 | PROC_LOCK(p); |
| 501 | if (!(p->p_flag & P_PROFIL)) { |
| 502 | PROC_UNLOCK(p); |
| 503 | return; |
| 504 | } |
| 505 | p->p_profthreads++; |
| 506 | prof = &p->p_stats->p_prof; |
| 507 | PROC_PROFLOCK(p); |
| 508 | if (pc < prof->pr_off || |
| 509 | (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size) { |
| 510 | PROC_PROFUNLOCK(p); |
| 511 | goto out; |
| 512 | } |
| 513 | |
| 514 | addr = prof->pr_base + i; |
| 515 | PROC_PROFUNLOCK(p); |
| 516 | PROC_UNLOCK(p); |
| 517 | if (copyin(addr, &v, sizeof(v)) == 0) { |
| 518 | v += ticks; |
| 519 | if (copyout(&v, addr, sizeof(v)) == 0) { |
| 520 | PROC_LOCK(p); |
| 521 | goto out; |
| 522 | } |
| 523 | } |
| 524 | stop = 1; |
| 525 | PROC_LOCK(p); |
| 526 | |
| 527 | out: |
| 528 | if (--p->p_profthreads == 0) { |
| 529 | if (p->p_flag & P_STOPPROF) { |
| 530 | wakeup(&p->p_profthreads); |
| 531 | p->p_flag &= ~P_STOPPROF; |
| 532 | stop = 0; |
| 533 | } |
| 534 | } |
| 535 | if (stop) |
| 536 | stopprofclock(p); |
| 537 | PROC_UNLOCK(p); |
| 538 | } |