| 814 | } |
| 815 | |
| 816 | int |
| 817 | kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, |
| 818 | struct itimerval *oitv) |
| 819 | { |
| 820 | struct proc *p = td->td_proc; |
| 821 | struct timeval ctv; |
| 822 | sbintime_t sbt, pr; |
| 823 | |
| 824 | if (aitv == NULL) |
| 825 | return (kern_getitimer(td, which, oitv)); |
| 826 | |
| 827 | if (which > ITIMER_PROF) |
| 828 | return (EINVAL); |
| 829 | #ifdef KTRACE |
| 830 | if (KTRPOINT(td, KTR_STRUCT)) |
| 831 | ktritimerval(aitv); |
| 832 | #endif |
| 833 | if (itimerfix(&aitv->it_value) || |
| 834 | aitv->it_value.tv_sec > INT32_MAX / 2) |
| 835 | return (EINVAL); |
| 836 | if (!timevalisset(&aitv->it_value)) |
| 837 | timevalclear(&aitv->it_interval); |
| 838 | else if (itimerfix(&aitv->it_interval) || |
| 839 | aitv->it_interval.tv_sec > INT32_MAX / 2) |
| 840 | return (EINVAL); |
| 841 | |
| 842 | if (which == ITIMER_REAL) { |
| 843 | PROC_LOCK(p); |
| 844 | if (timevalisset(&p->p_realtimer.it_value)) |
| 845 | callout_stop(&p->p_itcallout); |
| 846 | microuptime(&ctv); |
| 847 | if (timevalisset(&aitv->it_value)) { |
| 848 | pr = tvtosbt(aitv->it_value) >> tc_precexp; |
| 849 | timevaladd(&aitv->it_value, &ctv); |
| 850 | sbt = tvtosbt(aitv->it_value); |
| 851 | callout_reset_sbt(&p->p_itcallout, sbt, pr, |
| 852 | realitexpire, p, C_ABSOLUTE); |
| 853 | } |
| 854 | *oitv = p->p_realtimer; |
| 855 | p->p_realtimer = *aitv; |
| 856 | PROC_UNLOCK(p); |
| 857 | if (timevalisset(&oitv->it_value)) { |
| 858 | if (timevalcmp(&oitv->it_value, &ctv, <)) |
| 859 | timevalclear(&oitv->it_value); |
| 860 | else |
| 861 | timevalsub(&oitv->it_value, &ctv); |
| 862 | } |
| 863 | } else { |
| 864 | if (aitv->it_interval.tv_sec == 0 && |
| 865 | aitv->it_interval.tv_usec != 0 && |
| 866 | aitv->it_interval.tv_usec < tick) |
| 867 | aitv->it_interval.tv_usec = tick; |
| 868 | if (aitv->it_value.tv_sec == 0 && |
| 869 | aitv->it_value.tv_usec != 0 && |
| 870 | aitv->it_value.tv_usec < tick) |
| 871 | aitv->it_value.tv_usec = tick; |
| 872 | PROC_ITIMLOCK(p); |
| 873 | *oitv = p->p_stats->p_timer[which]; |
no test coverage detected