/* * The real-time timer, interrupting hz times per second. */ void hardclock(struct clockframe *frame) { struct proc *p; struct cpu_info *ci = curcpu(); p = curproc; if (p && ((p->p_flag & (P_SYSTEM | P_WEXIT)) == 0)) { struct process *pr = p->p_p; /* * Run current process's virtual and profile time, as needed. */ if (CLKF_USERMODE(frame) && timerisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) && itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], tick) == 0) { atomic_setbits_int(&p->p_flag, P_ALRMPEND); need_proftick(p); } if (timerisset(&pr->ps_timer[ITIMER_PROF].it_value) && itimerdecr(&pr->ps_timer[ITIMER_PROF], tick) == 0) { atomic_setbits_int(&p->p_flag, P_PROFPEND); need_proftick(p); } } /* * If no separate statistics clock is available, run it from here. */ if (stathz == 0) statclock(frame); if (--ci->ci_schedstate.spc_rrticks <= 0) roundrobin(ci); /* * If we are not the primary CPU, we're not allowed to do * any more work. */ if (CPU_IS_PRIMARY(ci) == 0) return; tc_ticktock(); ticks++; /* * Update real-time timeout queue. * Process callouts at a very low cpu priority, so we don't keep the * relatively high clock interrupt priority any longer than necessary. */ if (timeout_hardclock_update()) softintr_schedule(softclock_si); }
/* * 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. Schedule an AST that will vector us to * trap() with a context in which copyin and copyout will work. * Trap will then call addupc_task(). */ void addupc_intr(struct proc *p, u_long pc) { struct uprof *prof; prof = &p->p_p->ps_prof; if (pc < prof->pr_off || PC_TO_INDEX(pc, prof) >= prof->pr_size) return; /* out of range; ignore */ p->p_prof_addr = pc; p->p_prof_ticks++; atomic_setbits_int(&p->p_flag, P_OWEUPC); need_proftick(p); }