/* ARGSUSED */ int sys_profil(struct proc *p, void *v, register_t *retval) { struct sys_profil_args /* { syscallarg(caddr_t) samples; syscallarg(size_t) size; syscallarg(u_long) offset; syscallarg(u_int) scale; } */ *uap = v; struct uprof *upp; int s; if (SCARG(uap, scale) > (1 << 16)) return (EINVAL); if (SCARG(uap, scale) == 0) { stopprofclock(p); return (0); } upp = &p->p_p->ps_prof; /* Block profile interrupts while changing state. */ s = splstatclock(); upp->pr_off = SCARG(uap, offset); upp->pr_scale = SCARG(uap, scale); upp->pr_base = (caddr_t)SCARG(uap, samples); upp->pr_size = SCARG(uap, size); startprofclock(p); splx(s); return (0); }
/* * Stop profiling on a process. */ void stopprofclock(struct process *pr) { int s; if (pr->ps_flags & PS_PROFIL) { atomic_clearbits_int(&pr->ps_flags, PS_PROFIL); if (--profprocs == 0 && stathz != 0) { s = splstatclock(); psdiv = pscnt = 1; setstatclockrate(stathz); splx(s); } } }
/* * Start profiling on a process. * * Kernel profiling passes proc0 which never exits and hence * keeps the profile clock running constantly. */ void startprofclock(struct process *pr) { int s; if ((pr->ps_flags & PS_PROFIL) == 0) { atomic_setbits_int(&pr->ps_flags, PS_PROFIL); if (++profprocs == 1 && stathz != 0) { s = splstatclock(); psdiv = pscnt = psratio; setstatclockrate(profhz); splx(s); } } }
/* * Stop profiling on a process. */ void stopprofclock(struct proc *p) { int s; if (p->p_flag & P_PROFIL) { atomic_clearbits_int(&p->p_flag, P_PROFIL); if (--profprocs == 0 && stathz != 0) { s = splstatclock(); psdiv = pscnt = 1; setstatclockrate(stathz); splx(s); } } }
/* * Start profiling on a process. * * Kernel profiling passes proc0 which never exits and hence * keeps the profile clock running constantly. */ void startprofclock(struct proc *p) { int s; if ((p->p_flag & P_PROFIL) == 0) { atomic_setbits_int(&p->p_flag, P_PROFIL); if (++profprocs == 1 && stathz != 0) { s = splstatclock(); psdiv = pscnt = psratio; setstatclockrate(profhz); splx(s); } } }
/* * Define the code needed before returning to user mode, for * trap, mem_access_fault, and syscall. */ static inline void userret(struct proc *p, int pc, u_quad_t oticks) { int sig; /* take pending signals */ while ((sig = CURSIG(p)) != 0) psig(sig); p->p_pri = p->p_usrpri; if (want_ast) { want_ast = 0; if (p->p_flag & SOWEUPC) { p->p_flag &= ~SOWEUPC; ADDUPROF(p); } } if (want_resched) { /* * Since we are curproc, a clock interrupt could * change our priority without changing run queues * (the running process is not kept on a run queue). * If this happened after we setrq ourselves but * before we swtch()'ed, we might not be on the queue * indicated by our priority. */ (void) splstatclock(); setrq(p); p->p_stats->p_ru.ru_nivcsw++; swtch(); (void) spl0(); while ((sig = CURSIG(p)) != 0) psig(sig); } /* * If profiling, charge recent system time to the trapped pc. */ if (p->p_flag & SPROFIL) addupc_task(p, pc, (int)(p->p_sticks - oticks)); curpri = p->p_pri; }
/* * Define the code needed before returning to user mode, for * trap, mem_access_fault, and syscall. */ static inline void userret(struct proc *p, int pc, u_quad_t oticks) { int sig; /* take pending signals */ while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; if (want_ast) { want_ast = 0; if (p->p_flag & P_OWEUPC) { p->p_flag &= ~P_OWEUPC; ADDUPROF(p); } } if (want_resched) { /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we put ourselves on the run queue * but before we switched, we might not be on the queue * indicated by our priority. */ (void) splstatclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); (void) spl0(); while ((sig = CURSIG(p)) != 0) postsig(sig); } /* * If profiling, charge recent system time to the trapped pc. */ if (p->p_flag & P_PROFIL) addupc_task(p, pc, (int)(p->p_sticks - oticks)); curpriority = p->p_priority; }